P3403 跳楼机 同余最短路

链接:https://www.luogu.com.cn/problem/P3403

题意:给出了三个数字,让我们找出可以由这三个数字组合合成的所有数字数量(在一定范围内)

思路:第一次遇到这种题。我们先将这三个数按从小到大排序;

   分别表示为a,b,c;

   那么(b mod a) (c mod a),肯定是a的剩余系;

   什么是剩余系呢?其实就是余数;

   假设这三个数为3 4 5;

   那么a的余数有0 1 2,这三个数;

   我们的任务就是求出某数K的余数是(0或1或2)的最小整数;

   然后这些整数不断叠加a,直到大于这个范围;

   那么在这个范围内所叠加到的所有数,就是本题答案。

   于是,我们的任务就是找出最小整数,那么如何找出最小整数呢,我们可以通过建图,然后跑最短路的方式来得出。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define INF 0x3f3f3f3f
 4 #define N 1000010
 5 using namespace std;
 6 ll first[N],next[N],go[N],cost[N],tot;
 7 ll dist[N],vis[N],h,x,y,z,ans;
 8 inline void add_edge(ll u,ll v,ll w){
 9     next[++tot]=first[u];
10     first[u]=tot;
11     go[tot]=v;
12     cost[tot]=w;
13 }
14 inline void spfa(){
15     queue<ll>q;
16     memset(dist,INF,sizeof(dist));
17     memset(vis,0,sizeof(vis));
18     dist[0]=1;vis[0]=1;
19     q.push(0);
20     while(!q.empty()){
21         ll u=q.front();q.pop();
22         vis[u]=0;
23         for(ll e=first[u];e;e=next[e]){
24             ll v=go[e],w=cost[e];
25             if(dist[v]>dist[u]+w){
26                 dist[v]=dist[u]+w;
27                 if(!vis[v]){
28                     q.push(v);vis[v]=1;
29                 }
30             }
31         }
32     }
33 }
34 signed main()
35 {
36     scanf("%lld%lld%lld%lld",&h,&x,&y,&z);
37     if(x==1||y==1||z==1){printf("%d",h);return 0;}//可以直接到任何楼层
38     for(int i=0;i<=x-1;i++){
39         add_edge(i,(i+y)%x,y);
40         add_edge(i,(i+z)%x,z);
41     }
42     spfa();
43     for(int i=0;i<=x-1;i++){
44         if(dist[i]<=h) ans+=(h-dist[i])/x+1;//统计答案
45     }
46     printf("%lld",ans);
47     return 0;
48 }
View Code

 

   

posted @ 2020-05-19 18:58  古比  阅读(178)  评论(0编辑  收藏  举报