[洛谷P3403] 跳楼机
套路题,同余最短路。
先只考虑y、z进行连边,再在mod x的意义下进行计算。
这里的“距离”dis[i]指的是,在所有满足a mod x=i的a里,能到达的最小的a是多少。
显然只要能到达dis[i],每次加x即可到达dis[i]上面所有mod x=i的楼层。
最后根据计算出来的dis来统计答案。
统计到mod x=i的情况时,答案为(h-dis[i])/x+1。
其意义是,dis[i]到h的所有楼层,所有mod x=i的都可到达,即每x个就有一个可到达。
这么分析一波,这道题就很简单了。
然而我写dijkstra的时候,把小于号重载反了,WA声一片......
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define ll long long 6 using namespace std; 7 8 ll h,ans; 9 int x,y,z,ec; 10 int hd[100005],nx[200005],to[200005]; 11 ll dis[100005],len[200005]; 12 bool v[100005]; 13 14 void edge(int af,int at,ll el) 15 { 16 to[++ec]=at; 17 len[ec]=el; 18 nx[ec]=hd[af]; 19 hd[af]=ec; 20 } 21 22 struct data 23 { 24 int p; 25 ll d; 26 friend bool operator < (data q,data w) 27 { 28 return q.d>w.d; 29 } 30 }; 31 32 priority_queue<data>qq; 33 34 void dijkstra() 35 { 36 memset(dis,0x3f,sizeof(dis)); 37 dis[1%x]=1; 38 qq.push((data){1%x,1}); 39 while(!qq.empty()) 40 { 41 data np=qq.top(); 42 qq.pop(); 43 if(v[np.p])continue; 44 v[np.p]=1; 45 for(int i=hd[np.p];i;i=nx[i]) 46 { 47 if(!v[to[i]]&&dis[to[i]]>dis[np.p]+len[i]) 48 { 49 dis[to[i]]=dis[np.p]+len[i]; 50 qq.push((data){to[i],dis[to[i]]}); 51 } 52 } 53 } 54 } 55 56 int main() 57 { 58 scanf("%lld%d%d%d",&h,&x,&y,&z); 59 for(int i=0;i<x;i++) 60 { 61 edge(i,(i+y)%x,y); 62 edge(i,(i+z)%x,z); 63 } 64 dijkstra(); 65 for(int i=0;i<x;i++) 66 if(dis[i]<=h) 67 ans+=(h-dis[i])/x+1; 68 printf("%lld",ans); 69 return 0; 70 }