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 }
View Code

猜你喜欢

转载自www.cnblogs.com/Xu-daxia/p/9383204.html