poj 1879.Tempus et mobilius Time and motion

#include<stdio.h>

const int MAX_BALLS=127;
const int QUEUE_LENGTH=MAX_BALLS;

int nBalls;
int ans;
int qu[QUEUE_LENGTH+1];
int qs, qt;
int map[MAX_BALLS+1];
int cycles[MAX_BALLS+1];

//将elem入队.
void AddQueue(int elem);
//出队.
int DelQueue();
//模拟球钟半天的运作情况.
void Simulate();
//计算整数a和b的最大公约数并返回.
int Gcd(int a,int b);
//计算整数a和b的最小公倍数并返回.
int Lcm(int a,int b);

int main()
{
	int i, j;
	
	while(scanf("%d",&nBalls)!=EOF&&nBalls!=0){
		//初始化空闲队列.
		for(i=1;i<=nBalls;i++){
			qu[i]=i;
		} 
		qs=1;
		qt=nBalls;
		//模拟球钟一天的运作情况.
		Simulate();
		Simulate();
		if(qs<qt){
			j=qs+nBalls-1;
		} 
		else{
			j=qt;
		}
		for(i=qs;i<=j;i++){
			map[i-qs+1]=qu[(i-1)%QUEUE_LENGTH+1];
		}
		//计算各个小球首次回到初始时刻状态的天数.
		for(i=1;i<=nBalls;i++){
			cycles[i]=1;
			j=i;
			while(map[j]!=i){
				j=map[j];
				cycles[i]++;
			}
		} 
		//求解并输出.
		ans=cycles[1]; 
		for(i=2;i<=nBalls;i++){
			ans=Lcm(ans, cycles[i]);
		}
		printf("%d balls cycles after %d days.\n",nBalls,ans);
	}
	return 0;
} 

void AddQueue(int elem)
{
	qt=qt%QUEUE_LENGTH+1;
	qu[qt]=elem;
}

int DelQueue()
{
	int elem=qu[qs];
	qs=qs%QUEUE_LENGTH+1;
	return elem;
}

void Simulate()
{
	int n5MBalls,nHBalls;//分别为五分钟指示器和小时指示器中的小球数.
	int BallsOf5Minite[16],ballsOfHour[16];//分别为五分钟指示器和小时指示器的小球序列.
	int tmp[16];
	int i;
	
	for(nHBalls=1;nHBalls<=12;nHBalls++){
		for(n5MBalls=1;n5MBalls<=12;n5MBalls++){
			for(i=1;i<=5;i++){
				tmp[6-i]=DelQueue();
			}
				//将分钟指示器中的小球按放入时相反的顺序放入空闲球队列尾部.
			for(i=2;i<=5;i++){
				AddQueue(tmp[i]);
			} 
			BallsOf5Minite[n5MBalls]=tmp[1];
		}
			//五分钟指示器满,归还五分钟指示器中的小球和第12个小球.
		for(i=1;i<12;i++){
			AddQueue(BallsOf5Minite[12-i]);
		} 
		ballsOfHour[nHBalls]=tmp[1];
	}
	//小时指示器满,归还小时指示器中的小球和第12个小球.
	for(i=1;i<12;i++){
		AddQueue(ballsOfHour[12-i]);
	} 
	AddQueue(tmp[1]);
}

int Gcd(int a, int b)
{
	if(b==0){
		return a;
	}
	else{
		return Gcd(b,a%b);
	}
}
int Lcm(int a,int b)
{
	int tmp=Gcd(a,b);
	return a*(b/tmp);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值