POJ 3539 Elevator(同余类BFS)
题意
有一部电梯,最初停在1层。
电梯有4个按键,上升a,b,c层,回到一层。
求从一层出发。能到达1~h的哪些楼层。
(h<=1018,a,b,c<=105)
题解
这种h能大的图论,一眼就知道是同余类。
以模a[1]的余数为下标建立数组,数组的意义是模a[1]为下标的最小的能到达的值。
显然之后的相同模数的楼层都可以达到。统计答案即可。
处理数组用最短路就行。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const long long N=100100; 9 const long long INF=0x3f3f3f3f; 10 long long cnt,head[N]; 11 long long dis[N],book[N]; 12 long long a[5],h,ans; 13 struct edge{ 14 long long to,nxt,w; 15 }e[N*3]; 16 void add(long long u,long long v,long long w){ 17 cnt++; 18 e[cnt].nxt=head[u]; 19 e[cnt].to=v; 20 e[cnt].w=w; 21 head[u]=cnt; 22 } 23 void spfa(){ 24 queue<long long> q; 25 memset(dis,0x3f,sizeof(dis)); 26 cout<<dis[1]<<endl; 27 dis[1%a[1]]=1; 28 book[1%a[1]]=1; 29 q.push(1%a[1]); 30 while(!q.empty()){ 31 long long u=q.front(); 32 q.pop(); 33 book[u]=0; 34 for(long long i=head[u];i;i=e[i].nxt){ 35 long long v=e[i].to; 36 if(dis[v]>dis[u]+e[i].w){ 37 dis[v]=dis[u]+e[i].w; 38 if(book[v]==0){ 39 book[v]=1; 40 q.push(v); 41 } 42 } 43 } 44 } 45 } 46 int main(){ 47 scanf("%lld",&h); 48 scanf("%lld%lld%lld",&a[1],&a[2],&a[3]); 49 sort(a+1,a+1+3); 50 for(long long i=0;i<=a[1]-1;i++){ 51 add(i,(i+a[2])%a[1],a[2]); 52 add(i,(i+a[3])%a[1],a[3]); 53 } 54 55 spfa(); 56 for(long long i=0;i<=a[1]-1;i++){ 57 if(dis[i]<=h)ans+=(long long)(h-dis[i])/a[1]+1; 58 } 59 printf("%lld",ans); 60 return 0; 61 }