UVA 12108 Extraordinarily Tired Students(枚举)

When a student is too tired, he can’t help sleeping in class, even if his favorite teacher is right here in front of him.
当学生累了的时候,他顶不住了就要上课睡觉,哪怕老师就站在旁边
Imagine you have a class of extraordinarily tired students, how long do you have to wait,
想像你有一个很多特别累的学生,你需要等多久,学生才会听你讲课,不在继续睡觉?
before all the students are listening to you and won’t sleep any more? In order to complete this task,
you need to understand how students behave.
为了完成这个任务,首先明白学生们的行为.
When a student is awaken, he struggles for a minutes listening to the teacher (after all, it’s too bad to sleep all the time).
当一个学生醒着,他会挣扎着听老师讲a分钟(毕竟,他还没有坏到一直睡觉)
After that, he counts the number of awaken and sleeping students (including
himself).
在那之后,他会数数醒着和睡着的人数(包括他自己)
If there are strictly more sleeping students than awaken students, he sleeps for b minutes.
如果睡觉的人严格大于醒着的学生,他会睡b分钟
Otherwise, he struggles for another a minutes, because he knew that when there is
only very few sleeping students, there is a big chance for them to be punished!
否者他会继续挣扎a分钟,因为他知道只有很少睡觉的学生,他们很容易受到处罚。
Note that a student counts the number of sleeping students only when he wants to sleep again.
注意当一个学生开始数人数仅当他想睡觉的时候
Now that you understand each student could be described by two integers a and b,
the length of awaken and sleeping period.
既然你明白了每个学生可以用a和b两个整数来描述他们清醒和睡觉的时间
If there are always more sleeping students, these two periods continue again and
again.
如果睡觉的人一直都多余清醒的人,这样两个阶段会一直循环
We combine an awaken period with a sleeping period after it, and call the combined
period an awaken-sleeping period.
我们把清醒和睡觉的时间结合起来,叫做一个awaken-sleeing段
For example, a student with a = 1 and b = 4 has an awaken-sleeping period of awaken-sleeping-sleeping-sleeping-sleeping.
例如a=1,b=4 a-s-s-s-s
In this problem, we need another parameter c (1 ≤ c ≤ a + b) to describe a
student’s initial condition:
在这个问题中还需要另一个参数c(c>=1&&c<=a+b)用于描述一个学生的初始状态
the initial position in his awaken-sleeping period.
他在a-s段中的初始位置.
The 1st and 2nd position of the period discussed above are awaken and sleeping,
respectively.
相对于as周期的位置。
Now we use a triple (a, b, c) to describe a student. Suppose there are three
students (2, 4, 1), (1, 5, 2) and (1, 4, 3), all the students will be awaken at
time 18.
现在我们用一个三元组(a,b,c)描述一个学生。假设有三个学生(2,4,1)(1,5,2)(1,4,3)
会在时刻18时候全部清醒

The details are shown in the table below.
Table 1. An example
Write a program to calculate the first time when all the students are not sleeping.
Input
The input consists of several test cases.
多组测试用例
The first line of each case contains a single integer n (1 ≤ n ≤ 10), the number of students.
第一行n表示学生数
This is followed by n lines, each describing a student.
接下来n行输入描述学生的三元组
Each of these lines contains three integers a, b, c (1 ≤ a, b ≤ 5), described
above.
The last test case is followed by a single zero, which should not be processed.

Output
For each test case, print the case number and the first time all the students are
awaken. If it’ll never happen, output ‘-1’.
输出所有学生清醒的时刻,没有输出-1
Sample Input
3
2 4 1
1 5 2
1 4 3
6 5 6
a a s s s s a
s s s s s a s s s s s
s s s a s s s s
3
1 2 1
1 2 2
1 2 3
0
Sample Output
Case 1: 18
Case 2: -1
输入:
a,b>=1&&a,b<=5&&c>=1&&c<=10
判定是否存在一个清醒的时间点。
清醒的时间点相当于所有人在某个时刻的清醒时刻都重叠了。
a:a-s-s
s:a-s-s
s:a-s-s
a s s a s s
s s a s s a
s a s s a s

不管从周期那个位置开始,这个周期的长度都是不变的,求出所有周期的最小公倍数,如果在这
个最小公倍数中都没有出现清醒的时刻,说明永远都不可能清醒。
因为睡觉的机制需要在清醒时候如果数人数,睡觉人数大于清醒人数才能入睡
只要出现一次睡觉人数<=清醒人数的时刻t,那么最后一定有所有人都清醒的时刻。
因为t出现的时候清醒的人就不能够继续入睡了,那么只要等待剩下的人睡醒就是全部清醒了。
如果永远不可能清醒的话,在这个最小公倍数中,一定是每个位置都能满足睡觉的人多余清醒的人
假设其中有一个时刻清醒的人>=睡觉的人,那之后一定会一直清醒着,知道那几个睡觉的人也醒过来。
换言之,只要有清醒的人>=睡觉的人的时刻出现,就能够保证最后一定能够清醒。
如果最小公倍数中每一个时刻清醒的人<睡觉的人,就能够保证没有一刻全班清醒。

int n //学生数
int tlen[] //第i个学生的周期长度
state[][]  //第一维 学生的s-a周期序号 第二维 学生在周期的第几个时刻 
//0表示睡觉 1表示清醒
e = lck();//周期的最小公倍数
for(i=0;i<e;i++){
    int cnt= 0;
    for(j=0;j<n;j++){
        if(state[j][i%tlen[j]]==0) cnt++;
    }
    if(cnt<=n-cnt){//一定有清醒的时候
        //从这个时刻往后数到所有人都睡醒就好了。
        return 清醒的时刻;
    }
}
return -1;
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n;
int tlen[15];
int state[15][15];
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
int lck(int a,int b){
    return (a/gcd(a,b))*b;
}
int check(int e){
    int cnt;
    int i,j,k;
    for(i=0;i<e;i++){//枚举最小公倍数中每一个时刻
        //cout<<"ggg"<<endl;
        cnt = 0;
        for(j=0;j<n;j++){//然后对这一时刻枚举每一个学生的状态
            if(state[j][i%tlen[j]]==0) cnt++;//在这个时刻这个学生的状态为睡觉
        }
        //cout<<cnt<<","<<n-cnt<<endl;

        if(cnt<=n-cnt){//清醒的人不少于睡觉的人最后一定能够全部都清醒
            int Max = 0;
            int cnt2;
            //从这个时刻往后醒着的一直醒着,等待睡着的睡醒
            for(j=0;j<n;j++){
                if(state[j][i%tlen[j]]==0){//如果在当前时刻还在睡的检查还需要多久才能醒,取个最大值
                    cnt2 = 0;
                    for(k=i+1;;k++){
                        cnt2++;
                        if(state[j][k%tlen[j]]==1) break;//醒了就退出
                    }
                    if(cnt2>Max) Max = cnt2;
                }
            }
            return i+Max;
        }

    }
    return -1;//没有一个时刻清醒的数不少于睡觉的人数
}
void print(){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<tlen[i];j++){
            cout<<state[i][j]<<" ";
        }
        cout<<endl;
    }
}
int main()
{
    //#define LOCAL
    #ifdef LOCAL
    freopen("in","r",stdin);
    freopen("out","w",stdout);
    #endif
    int Case = 1;
    int a,b,c,i,j,k;
    while(cin>>n&&n){
        cout<<"Case "<<Case++<<": ";
        for(i=0;i<n;i++){
            cin>>a>>b>>c;
            tlen[i] = a+b;
            for(j=0;j<a;j++) state[i][j] = 1;
            for(;j<a+b;j++) state[i][j] = 0;
            //for(j=0;j<a+b;j++) cout<<state[i][j];cout<<endl;
            //周期循环左移c-1位
            c = c-1;
            int t[15];
            for(j=0;j<c;j++) t[j] = state[i][j];
            for(j=c;j<a+b;j++) state[i][j-c] = state[i][j];
            for(j=a+b-c;j<a+b;j++) state[i][j] = t[j-(a+b-c)];
            //for(j=0;j<a+b;j++) cout<<state[i][j];cout<<endl;
        }
        //print();
        int e = tlen[0];
        for(i=1;i<n;i++){
            e = lck(e,tlen[i]);
        }
        int time = check(e);
        if(time==-1) cout<<-1<<endl;
        else cout<<time+1<<endl;
    }
    return 0;
}

 

posted @ 2019-06-16 12:37  fanyuheng  阅读(106)  评论(0)    收藏  举报