特别困的学生(Extraordinarily Tired Students, ACM/ICPC Xi'an 2006, UVa12108)

本文介绍了一个关于学生睡眠周期的模拟问题。在一个班级中,每个学生都有自己的清醒和睡眠周期,当班级中睡觉的学生数量严格大于清醒的学生时,学生才会进入睡眠状态。文章详细解释了如何通过编程模拟这一过程,以找出所有学生都清醒所需的时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

课堂上有n个学生(n≤10)。每个学生都有一个“睡眠-清醒”周期,其中第i个学生醒A i 分
钟后睡B i 分钟,然后重复(1≤A i ,B i ≤5),初始时第i个学生处在他的周期的第C i 分钟。每个
学生在临睡前会察看全班睡觉人数是否严格大于清醒人数,只有这个条件满足时才睡觉,否
则就坚持听课A i 分钟后再次检查这个条件。问经过多长时间后全班都清醒。如果用(A,B,C)描
述一些学生,则图4-11中描述了3个学生(2,4,1)、(1,5,2)和(1,4,3)在每个时刻的行为。

原题比较长 总结下来大意是这样的

1 输入 n 代表有n个人 接下来是n 个a b c  a表示 清醒的时间 b表示睡觉的时间 c表示现在到了哪一个时间 (a+b表示一个周期 c则表示到了这个周期那个时间点上)

2 如果有半数或者半数以上的人没有睡觉 则不会继续睡下去了(就是一直醒着不会再睡了)。

所以我们可以这样做:

我们可以的到一个思路直接那就是直接的模拟每个时刻然后判断这个时刻是否有小于一半的人在睡觉

如果有超过一半没有睡眠那么则循环到最后一个睡醒的位置输出结果

如果在进行时发现当前的状态等于最开始的状态就表示出现了周期循环,那么则无解

由此我们就可以的得到代码(转载

#include <iostream>
#include <cstdio>
using namespace std;
 
struct student {
	int wake;
	int sleep;
	int loc;
} stu[10];
 
int main() 
{
	//freopen("input.in","r",stdin);
	//freopen("output.out","w",stdout);
	int n;
	int index=1;
	while(cin>>n) {
		if(n==0) break;
		int start[10];
		int sleep=0;
		for(int i=0; i<n; i++) {
			cin>>stu[i].wake>>stu[i].sleep>>stu[i].loc;
			stu[i].loc--;
			start[i]=stu[i].loc;
			if(stu[i].loc>stu[i].wake-1)
				sleep++;
		}
		long long time=0;
		while(++time) {
			bool flag=0;
			if(sleep>n-sleep) flag=1;//如果睡觉的的人多
			for(int i=0; i<n; i++) {			
				//同时处于马上要睡着的人,这时就睡着
				//注意这里要判断是不是第一次,要是第一次就不进行计算 
				if(time == 1)break;
				if(flag) {
					if(stu[i].loc==stu[i].wake)//表示下一个时间段是睡眠 把睡眠数 +1  
						sleep++;
					if(stu[i].loc==0)
						sleep--;
				} else  {
					if(stu[i].loc==stu[i].wake)
						stu[i].loc=0;
					else if(stu[i].loc==0)
						sleep--;
				}
			}
			bool flag2=1;
			if(time==1) flag2=0;
			for(int i=0; i<n; i++) {
				//判断是否与开始时的状态相同 
				if(stu[i].loc!=start[i]) flag2=0;
				//然后对每个同学所处的位置自增 
				stu[i].loc++;
				//不过要保证在这个区间内 
				stu[i].loc%=(stu[i].sleep+stu[i].wake);
			}
			if(sleep==0)
				break;
			if(flag2) {
				//cout<<time<<endl;
				time=-1;
				break;
			}
			//cout<<"sleep:"<<sleep<<endl;
		}
		cout<<"Case "<<index++<<": "<<time<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值