《黑书》数据结构:poj1879小球钟——时间与运动
黑书P38,这是黑书给出的思路:
我就是按照这个思路来编写的,不过有几个需要注意的地方,导致我wa了几次。
先说说我自己编完这道题目的想法吧:看完这道题目,我的想法是按照一分钟一分钟去模拟,再判断哪天会是全部相等,但无疑,我那种想法必定超时。然后看了黑书的思路,
发现原来有周期的是可以这样做的......学到了,以后对于类似的题目,可以思考这么做,求出单个的周期,再求它们的最小公倍数......
注意:可以这样做的条件,是必须要是初始和末尾状态相同的,就这道题目来说,小球是要全部在底层的队列里面才可以这样思考的,那么,当不是所有的小球都在底层的时候,我们必须要使它们到底层的时候,才能这样操作的.......如此来说,我们可以以半天也就是12个小时为一次置换也是可以的......
好吧,废话不多说了,编这个代码要注意几点,
1、对于怎么建立起置换的,这个我是用递归实现的,这也是我代码喂猫跑这么长时间的原因!
2、在模拟完所有情况的时候,在将要建立置换前,先要考虑有的小球,在不用置换就已经是原来的位置了......就是说,位置不会改的点......
3、注意,已经有了周期的点,不需要再改变.....也就是说只要第一个周期,这个一开始我考虑了,后来写的时候忘了........
#include<iostream> #include<queue> #include<stack> #include<stdio.h> #include<string.h> using namespace std; int a[7005],vist[7005],flg; int gcd(int m,int n) { if(m<n) { int tmp=m; m=n; n=tmp; } int r; while(m%n!=0) { r=m%n; m=n; n=r; } return n; } void digui(int b[],int c[],int d[],int num,int n) { if(b[flg]==num) { d[flg]=c[num]; vist[flg]=1; return; } int i=1; for(;i<=n;i++) if(b[i]==num) break; digui(b,c,d,i,n); d[i]=c[num]; vist[i]=1; } int main() { int n; while(scanf("%d",&n)>0&&n) { queue<int>Q; stack<int>s1; stack<int>s2; stack<int>s3; for(int i=1;i<=n;i++) { a[i]=i; Q.push(a[i]); } int i=1; while(1) { if(i>1440) break; int tmp=Q.front(); Q.pop(); if(i%5!=0) s1.push(tmp); else { s1.push(tmp); int tmp1=s1.top(); s1.pop(); s2.push(tmp1); while(!s1.empty()) { int tmp2=s1.top(); s1.pop(); Q.push(tmp2); } } if(i%60==0) { int tmp1=s2.top(); s2.pop(); s3.push(tmp1); while(!s2.empty()) { int tmp2=s2.top(); s2.pop(); Q.push(tmp2); } } if(i%720==0) { int tmp1=s3.top(); s3.pop(); while(!s3.empty()) { int tmp2=s3.top(); s3.pop(); Q.push(tmp2); } Q.push(tmp1); } i++; } int b[7005],c[7005],d[7005]; int j=1; while(!Q.empty()) { int tmp1=Q.front(); Q.pop(); c[j]=b[j]=tmp1; j++; } memset(a,-1,sizeof(a)); for(i=1;i<=n;i++) if(b[i]==i) a[i]=1; int w=1; /* for(i=1;i<=n;i++) printf("%d ",c[i]); printf("\n"); i=1; memset(vist,0,sizeof(vist)); while(i<=n) { if(!vist[i]) { flg=i; digui(b,c,d,i,n); } i++; } for(i=1;i<=n;i++) printf("%d ",d[i]); printf("\n"); */ while(1) { for(i=1;i<=n;i++) if(a[i]==-1) break; if(i>n) break; i=1; memset(vist,0,sizeof(vist)); while(i<=n) { if(!vist[i]) { flg=i; digui(b,c,d,i,n); } i++; } w++; j=1; for(;j<=n;j++) { c[j]=d[j]; if(a[j]==-1&&d[j]==j) { a[j]=w; } } } int tmp=a[1]; for(i=2;i<=n;i++) { tmp=tmp*a[i]/gcd(tmp,a[i]); } printf("%d balls cycle after %d days.\n",n,tmp); } return 0; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。