[] Jumping machine LGOJ3403

一栋楼共有 h 层,有以下操作:
1. 向上移动x层
2. 向上移动y层
3. 向上移动z层
4. 回到第一层
问可以达到的楼层数量

If so \ (f (i) \) represents represented only by operating the operation and 2 can reach. 3 \ (MOD \ X = I \) minimum floor
then there is the following equation:
\ [F (I + Y) = F (I) + Y \]
\ [F (I + Z) = F (I) + Z \]
think shortest transfer equation
\ [f (v) = f (u) + dis (u, v) \]

It is not like?
So we can build a map, the \ (i + y \) and \ (i + z \) seen as the point
\ (y, z \) be the weights, running spfa calculated \ (f (i) \)

Because of \ (f (i) \) without the use of a first amount of operation statistics
so each additional \ (X \) , the answer will increase accordingly

Note that the border is closed interval, so the answer then +1, i.e.
\ [ans + = (hf ( i)) / x + 1 \]

Code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll h,x,y,z,ans=0;
ll f[100005];
struct Edge
{
    ll next,to,dis;
}edge[200005];
int cnt=0,head[200005];

inline void add_edge(ll from,ll to,ll dis)
{
    edge[++cnt].next=head[from];
    edge[cnt].to=to;
    edge[cnt].dis=dis;
    head[from]=cnt;
}

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
bool vis[100005];
queue<int> q;
void spfa()
{
    memset(f,0x3f3f3f3f,sizeof(f));
    memset(vis,0,sizeof(vis));
    q.push(1);
    vis[1]=f[1]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(register int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(f[v]>f[u]+edge[i].dis)
            {
                f[v]=f[u]+edge[i].dis;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}

int main()
{
    read(h);
    read(x);read(y);read(z);
    if(x==1||y==1||z==1){printf("%lld\n",h);return 0;}
    for(register int i=0;i<x;++i)
    {
        add_edge(i,(i+y)%x,y);
        add_edge(i,(i+z)%x,z);
    }
    spfa();
    for(register int i=0;i<x;++i) if(f[i]<=h) ans+=(h-f[i])/x+1;
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/tqr06/p/11620680.html