【挖坑记】JZOJ 4722 跳楼机

题目大意

一幢大楼高为h,有四种操作,前三种分别是上升x、y、z层楼,最后一个是回到一楼。
h<=1e15,x,y,y<=1e5
时间限制1s
空间限制256M

解题思路

首先有一个数组d[i]=c,表示在c mod z=i的情况下,只用前两种操作可以达到的最小高度,然后 ans=z1i=0trunc((hd[i])/z)+1
而d数组的求解可以用最短路

#include
#include
#include
#define maxn 100006
#define fr(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll ding=100002;

int i,x,y,z,f[maxn];
ll n,ans,dis[maxn];
bool kan[maxn];
void spfa()
{
    int u,i=0,j=1;
    f[1]=1;
    dis[1]=1;
    kan[1]=1;
    while (i!=j)
    {
        i=i%ding+1;
        u=f[i];
        if (dis[(u+y)%z]>dis[u]+y)
        {
            dis[(u+y)%z]=dis[u]+y;
            if (!kan[(u+y)%z])
            {
                j=j%ding+1;
                f[j]=(u+y)%z;
                kan[(u+y)%z]=1;
            }
        }
        if (dis[(u+x)%z]>dis[u]+x)
        {
            dis[(u+x)%z]=dis[u]+x;
            if (!kan[(u+x)%z])
            {
                j=j%ding+1;
                f[j]=(u+x)%z;
                kan[(u+x)%z]=1;
            }
        }
        kan[u]=0;
    }
    return;
}
int main()
{
    scanf("%lld",&n);
    scanf("%d%d%d",&x,&y,&z);
    memset(dis,63,sizeof(dis));
    spfa();
    fr(i,0,z-1)
        if (dis[i]<=n) ans+=(n-dis[i])/z+1;
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(挖坑记)