POJ 1879 Tempus et mobilius Time and motion 队列和栈

很简单的队列和栈的应用,不过读明白题意非常重要:(直接引用白书的题解)三个轨道,一个库。分别是分钟单位的轨道,5min单位的轨道,一小时单位的轨道,还有就是n容量的库。每过一分钟,一个小球从库里面出来,库符合先进先出,进入分钟轨道,如果分钟轨道里面已经有了4个,那么这四个就滑入库,而这个球则进入5min轨道,如果5min轨道已经有了11个,这11个就滑入库,而这个球则滑入小时轨道,如果小时轨道已经有了11个,则这11个滑入库,这个球最后滑入库。在轨道中的球滑入库中,轨道里的球满足先进后出。如此,轨道是栈,库是队列。而且模拟过程也出来了。暴力会爆。

把小球分开模拟,先求出每个小球回到原来位置上的周期,然后求所有小球周期的最小公倍数。小球编号:1..n;然后模拟小球24小时的情况,得到一天后库里的队列:p1,p2..pn;这样实际上是建立了一种置换:F(1..n)=(p1,p2..pn);对于当前处于x位置的小球,一天后,都处于px,这样,可以求出每个小球回到原位置的周期,再求所有的周期的最小公倍数即可。

可以学到几个基础的东西:

一个序列经过变换,最终到达某个状态,如果要找到某个值经过了多少次变换到达的,这个程序中有。

求最大公约数的方法,那个gcd函数(有很多种,详见百度百科)

求最小公倍数的方法,lcm函数

 

#include<cstdio>

#include<algorithm>

#include<queue>

#include<stack>

using namespace std;

int gcd(int a,int b){

    while(b^=a^=b^=a%=b);

    return a;

}

inline int lcm(int a,int b){

    return a*b/gcd(a,b);

}

int n;

int main(){

    while(scanf("%d",&n)&&n){

        stack <int> mins,fivmin,hours;

        queue <int> all_ball;

        for(int i=1;i<=n;i++)all_ball.push(i);

        int cir=24*60;

        int m;

        while(cir--){

            m=all_ball.front();

            all_ball.pop();

            if(mins.size()==4){

                for(int i=0;i<4;all_ball.push(mins.top()),mins.pop(),i++);

                if(fivmin.size()==11){

                    for(int i=0;i<11;all_ball.push(fivmin.top()),fivmin.pop(),i++);

                    if(hours.size()==11){

                        for(int i=0;i<11;all_ball.push(hours.top()),hours.pop(),i++);

                        all_ball.push(m);

                    }else hours.push(m);

                }else fivmin.push(m);

            }else mins.push(m);

        }

        int arr[128];

        for (int i = 1; i <= n; i++) {

            arr[i] = all_ball.front();

            all_ball.pop();

        }

        int brr[128];

        for (int i = 1; i <= n; i++)

            brr[i] = 1;

        for (int i = 1; i <= n; i++) {

            int aa = arr[i];

            while (aa != i) {

                brr[i]++;

                aa = arr[aa];

            }

        }

        int sum = 1;

        for (int i = 1; i <= n; i++) {

            sum = lcm(sum, brr[i]);

        }

        printf("%d balls cycle after %d days.\n",n,sum);

    }

    return 0;

}

你可能感兴趣的:(time)