标签:
本题链接:点击打开链接
本题大意:
有一计时器,由编号从1到n的球组成,有三个轨道,分别对应1分钟,5分钟,1小时。此三个轨道可认为是栈,每分钟从球堆里出来一个球,球堆可认为是队列,三个轨道的容纳量分别是4,11,11。球首先进入的是1分钟轨道,当第五个球进入时,一分钟轨道的球全部出栈,进入球队列。而第五个球进入5分钟轨道,5分钟轨道满后再进的球进入小时轨道,5分钟轨道的球全部出栈进入球队列。小时轨道满了也是如此。此时经过半天。问:经过多少天球回归到原始状态。
解题思路:
每半天球完成一次序列交换,但问的是需多少天,故需先模拟出一天球的序列交换,然后求循环的最小公倍数。(我目前只能模拟出一天中球的序列交换,但如何求球需多少天回归原始状态还是不理解)。具体请参见代码:
#include<stdio.h> #include<string.h> #include<stack> #include<queue> using namespace std; int next[7005],mark[7005]; long long gcd(long long a,long long b)//最大公约数 { if(!b) return a; else return gcd(b, a % b); } long long lcm(long long x,long long y)//最小公倍数 { return x / gcd(x, y) * y; } int main() { int n; while(scanf("%d",&n),n) { queue <int> q; stack <int> min,five,hour; for(int i=1;i<=n;i++) q.push(i);//按标号使球进队列 for(int t=0;t<12*60*2;t++)//模拟一天中球的运动 { int now=q.front();//每次出来的是队首的球 q.pop(); if(min.size() < 4)//若1分钟轨道未满,则进入此轨道 min.push(now); else { for(int i=1;i<=4;i++)//若此轨道满,将此轨道的球进入球队列 { q.push(min.top()); min.pop(); } if(five.size() < 11)//然后判断5分钟球是否已满,未满,则进入此轨道 five.push(now); else { for(int i=1;i<=11;i++)//若5分钟球已满,此轨道球进入球队列 { q.push(five.top()); five.pop(); } if(hour.size() < 11)//进而判断小时轨道 hour.push(now); else { for(int i=1;i<=11;i++) { q.push(hour.top()); hour.pop(); } q.push(now); } } } } for(int i=1;i<=n;i++)//将一天中球的位置存到next数组 { next[i]=q.front(); q.pop(); } memset(mark,0,sizeof(mark)); long long sum=1; for(int i=1;i<=n;i++)//查找完成一次循环所需最少天数 { if(!mark[i]) { long long cnt=1; mark[i]=1; int t=next[i];//将第i个球的标号给t while(!mark[t]) { mark[t]=1; cnt++; t=next[t]; } sum=lcm(sum,cnt); } } printf("%d balls cycle after %lld days.\n",n,sum); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
poj 1879 Tempus et mobilius Time and motion
标签:
原文地址:http://blog.csdn.net/lsgbb/article/details/47614079