标签:
本题链接:点击打开链接
本题大意:
有一计时器,由编号从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