D 斩杀线计算大师 同余最短路
链接:https://ac.nowcoder.com/acm/contest/4853/D
思路:直接按同余最短路的方式建最短路找出最小剩余系;
然后找出满足条件的余数进行操作即可
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],nxt[N],go[N],cost[N],tot; 7 ll dist[N],vis[N],h,x,y,z,ans; 8 void add_edge(ll u,ll v,ll w){ 9 nxt[++tot]=first[u]; 10 first[u]=tot; 11 go[tot]=v; 12 cost[tot]=w; 13 } 14 void spfa() 15 { 16 queue<ll>q; 17 memset(dist,INF,sizeof(dist)); 18 memset(vis,0,sizeof(vis)); 19 dist[0]=0;vis[0]=1; 20 q.push(0); 21 while(!q.empty()){ 22 ll u=q.front();q.pop(); 23 vis[u]=0; 24 for(ll e=first[u];e;e=nxt[e]){ 25 ll v=go[e],w=cost[e]; 26 if(dist[v]>dist[u]+w){ 27 dist[v]=dist[u]+w; 28 if(!vis[v]){ 29 q.push(v); 30 vis[v]=1; 31 } 32 } 33 } 34 } 35 } 36 int main() 37 { 38 scanf("%lld%lld%lld%lld",&x,&y,&z,&h); 39 if(x==1||y==1||z==1){printf("%d",h);return 0;}//可以直接到任何楼层 40 for(int i=0;i<=x-1;i++){ 41 add_edge(i,(i+y)%x,y); 42 add_edge(i,(i+z)%x,z); 43 } 44 spfa(); 45 for(int i=0;i<=x-1;i++){ 46 if(dist[i]<=h){ 47 if((h-dist[i])%x==0){ 48 // printf("dist:%lld\n",dist[i]); 49 for(ll k=dist[i]/y;k>=0;k--){ 50 ll tmp=dist[i]-k*y; 51 if(tmp%z==0){ 52 printf("%lld %lld %lld\n",(h-dist[i])/x,k,tmp/z); 53 return 0; 54 } 55 } 56 } 57 } 58 } 59 return 0; 60 }