《黑书》数据结构: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;
}
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。

浙公网安备 33010602011771号