题意:
每个学生(1<=n<=10)存在一个awake-sleep周期,当这个学生到awake的最后一刻时,他要判断当前睡觉和醒的学生的人数,如果睡觉的人数绝对大于醒着的人数,那么他要继续保持清醒a分钟,否则就进入睡觉状态。
给出n个学生的清醒周期和睡觉周期以及初始时刻处于周期的时刻,判断什么时刻全班同学都清醒着,如果不存在这样的时刻,那么就输出-1.
分析:
只需要计算每个时刻全班的清醒人数和睡觉人数:更新每位同学的状态。然后判断是否awake人数==n即可。
完全模拟!
难点:
①对每个学生每个时刻参量的描述,可用结构体!
②每个时刻的状态判断
③大的循环时间的选择
#include <stdio.h> #include <string.h> #define maxn 15 struct STUDENT { int A;//清醒A分钟 int B;//睡B分钟 int C;//当前处于的周期时间C分钟 int D;//周期总时间 int is_sleep;//当前时间是不是睡着 }st[maxn]; int cases = 0, n; int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); while (~scanf("%d", &n) && n) { int ALL = 1;//所有学生的醒睡总周期 int awake = 0, sleep = 0;//全班清醒人数和睡觉人数 for (int i = 0;i < n;i++) { scanf("%d%d%d", &st[i].A, &st[i].B, &st[i].C); st[i].D = st[i].A + st[i].B; if (st[i].C <= st[i].A) { st[i].is_sleep = 0; awake++; } else { st[i].is_sleep = 1; sleep++; } ALL *= st[i].D; } int time;//当前时间 int flag=0;//标记是否存在全班都清醒的时刻 for (time = 1;time <= ALL;time++)//只需要判断从初始回到初始这个时间段的情况 { if (awake == n) { flag = 1; break; } int pre_sleep = sleep;//pre_sleep是上一时刻睡觉人数 int pre_awake = awake;//pre_awake是上一时刻清醒人数 for (int i = 0;i < n;i++) { st[i].C++;//下面就在i位学生周期的C时刻该学生的状态进行讨论 //只有两种变化(醒->睡和睡->醒)时才需更新状态,其余情况只需C叠加 if (st[i].C == (st[i].D + 1))//睡->醒 { st[i].C = 1; st[i].is_sleep = 0; sleep--; awake++; } else if (st[i].C == (st[i].A + 1))//醒->睡 { if (pre_sleep > pre_awake) { //这点很重要!sleep和awake是变化当前状态,而需要判断的实际上是上一时刻 st[i].is_sleep = 1; sleep++; awake--; } else st[i].C = 1; } } } if (flag) printf("Case %d: %d\n", ++cases, time); else printf("Case %d: %d\n", ++cases, -1); } return 0; }