POJ3539 Elevator 【同余类最短路】
作者:互联网
题目描述:
电梯有n层,开始在1层,每次可以向上升a,b,c层,问可以到达的层数。
n<=1018,1<=a,b,c<=100000
题目分析:
把楼层对a取模,按余数分成a类。同一余数的楼层只要最低的那层可达,其它所有都可达。
所以只需要考虑上升b,c层,求出模a余i的可达的最低的楼层。
设dis[i]表示模a余i可达的最低的楼层,转移是显然的:
dis[i]=min(dis[i],dis[(i−b)%a],dis[(i−c)%a])
转移有环,把每个类看成一个点,跑最短路即可,这就是同余类最短路。
Code:
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 100005
#define LL long long
using namespace std;
int a,b,c;
bool inq[maxn];
LL dis[maxn],n,ans;
queue<int>q;
inline void upd(int x,LL y){
if(dis[x]>y){
dis[x]=y;
if(!inq[x]) inq[x]=1,q.push(x);
}
}
void SPFA(){
memset(dis,0x3f,sizeof dis);
dis[1]=1,q.push(1);
while(!q.empty()){
int x=q.front();q.pop(),inq[x]=0;
upd((x+b)%a,dis[x]+b),upd((x+c)%a,dis[x]+c);
}
}
int main()
{
freopen("elevator.in","r",stdin);
freopen("elevator.out","w",stdout);
scanf("%lld%d%d%d",&n,&a,&b,&c);
if(a==1) return printf("%lld\n",n),0;
SPFA();
for(int i=0;i<a;i++) if(dis[i]<=n) ans+=(n-dis[i])/a+1;
printf("%lld\n",ans);
}
标签:int,LL,inq,Elevator,同余类,楼层,include,POJ3539,dis 来源: https://blog.csdn.net/C20181220_xiang_m_y/article/details/100108746