POJ 1879 Tempus et mobilius Time and motion(黑书,小球钟)

题目链接:Tempus et mobilius Time and motion

解题思路:使用三个栈和一个队列来模拟,三个栈分别代表1分钟,5分钟,1小时,一个队列就是之前所说的小球队列。当时间到达1:00的时候小球应该都在小球队列中,那么我们模拟12小时,让时间从1:00到1:00,之后观察小球的队列,这时记下小球的位置,说明12小时候原来i位置的小球会变道j位置上,对没一个小球的位置进行跟踪,算出需要多少个周期才能让自己回到原位。最后对所有小球的周期求最小公倍数。由于我们的周期是12小时,所以最小公倍数再除以2才能得到天数。

#include<stdio.h>
#include<stack>
#include<queue>
#include<string.h>
#define MAX 1000

using namespace std;

stack<int> mins, fmins, hour;
queue<int> q;
int v[MAX], tot[MAX];

void hourss(int t){
	if(hour.size() == 11){
		while(!hour.empty()){
			q.push(hour.top());
			hour.pop();
		}
		q.push(t);
		q.pop();
	}
	else{
		hour.push(t);
		q.pop();
	}
	
}

void fminss(int t){
	if(fmins.size() == 11){
		while(!fmins.empty()){
			q.push(fmins.top());
			fmins.pop();
		}
		hourss(t);
	}
	else{
		fmins.push(t);
		q.pop();
	}
}

void minss(int t){
	if(mins.size() == 4){
		while(!mins.empty()){
			q.push(mins.top());
			mins.pop();
		}
		fminss(t);
	}
	else{
		mins.push(t);
		q.pop();
	}
}

void init(){
	while(!q.empty())q.pop(); 
	while(!mins.empty())mins.pop();
	while(!fmins.empty())fmins.pop();
	while(!hour.empty())hour.pop();
	
}

int gcd(int a, int b){
	return b == 0 ? a :gcd(b, a % b);
}

int main(){
	int i, j, k;
	int n, tem, ans;
	//freopen("1.out", "w", stdout);
	while(scanf("%d", &n) && n){
		init();
		tem = 1;
		for(i = 0; i < n; i++){
			q.push(i);
		}
		for(i = 0; i < 720; i++){
			minss(q.front());
			//printf("No%d: %d %d %d\n", tem++, mins.size(), fmins.size(), hour.size());
		}
		i = 0;
		while(!q.empty()){
			v[q.front()] = i++;
			q.pop();
		}
		for(i = 0; i < n; i++){
			int s = v[i];
			int index = 1;
			while(s != i){
				s = v[s];
				index++;
			}
			tot[i] = index;
		}
		ans = tot[0];
		for(i = 1; i < n; i++){
			ans = ans * tot[i] / gcd(ans, tot[i]);
		}
		printf("%d balls cycle after %d days.\n", n, ans >> 1);
	}
	return 0;
}


 

你可能感兴趣的:(POJ 1879 Tempus et mobilius Time and motion(黑书,小球钟))