《黑书》数据结构: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;
}

 

posted @ 2013-05-30 19:56  紫忆  阅读(693)  评论(0编辑  收藏  举报