题解 P3403 【跳楼机】
主要的思想是要将题目转为最短路。我们假设dis[i]是y和z可达到的楼层mod x=i的最低楼层。将i从0到x-1枚举一遍,最终得到的便是所有在h范围内余数从0到x-1可达到的位置全部相加,即
而其中比较关键的一个点就是要将所有的dis[i]求出来,这就需要最短路。而最短路需要的图要由
这题有一个坑,就是第一组数据,x,y,z存在1且是乱序。必须要从大到小排序,否则结果会是0,当然也可以进行特判
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 500010;
long long ans, h, x, y, z, vis[N], dis[N], head[N], Next[N], ver[N], edge[N], tot;
queue <int> q;
void add(int x,int y,int z)//边表
{
ver[++tot]=y;
edge[tot]=z;
Next[tot]=head[x];
head[x]=tot;
}
void spfa()//最短路
{
memset(dis,0x3f3f3f,sizeof(dis));
q.push(1);
dis[1]=1;
while(q.size())
{
int x=q.front();
q.pop();
vis[x]=1;
for(int i=head[x];i;i=Next[i])
{
int y=ver[i];
if(dis[y]>dis[x]+edge[i])
{
dis[y]=dis[x]+edge[i];
if(!vis[y]) q.push(y);
vis[y]=1;
}
}
vis[x]=0;
}
}
int main()
{
scanf("%lld%lld%lld%lld",&h,&x,&y,&z);
if(y<z) swap(y,z);
if(x<y) swap(x,y);//将x,y,z按从大到小排序,x余数范围尽量大,过第一点
for(int i=0;i<x;i++)//建图
{
add(i,(i+y)%x,y);//f(i+y)=f(i)+y 到达mod x=i+y的层数就是相当于先跑到mod x=i的层数在往上跑y层
add(i,(i+z)%x,z);//f(i+z)=f(i)+z 同上
}
spfa();//跑一遍最短路
for(int i=0;i<x;i++)
{
if(h>=dis[i]) ans+=(h-dis[i])/x+1;//如果可以mod x=i时y和z可以达到的最低楼比总高度小,那就加上它的倍数(在h范围内),还要包括它自己
}
printf("%lld",ans);
return 0;
}