习题4-8 特别困的学生 UVa12108
感悟。
1、从网站下载英文原题,重点在看输入输出数据与格式。
2、英文原题第一遍读下来,对参数c一直不是很理解,In this problem, we need another parameter c
(1 <=c<= a + b) to describe a student’s initial condition: the initial position in his awaken-sleeping
period.借助中文书中的中文意思,弄明白了,c是描述该学生在他周期的第c分钟,描述学生的初始状态。
3、After that, he counts the number of awaken and sleeping students (including
himself).此句中的包括学生本人,学生本人是算在醒的人数里,还是睡着的人数里,表示不清楚。本人的理解是放在醒着的人数里。通过阅读英文原题中的样例表格得到印证。
4、题目读懂后,此题涉及周期性,故取模运算比较重要,先考虑该怎么编码,再动手。
5、先编写输入输出。
6、描述学生,用结构体比较方便。
7、不存在清醒时刻的初步设想:记下第一时刻状态,不存在全部清醒,那肯定存在周期性,下一个周期开始时刻与第一时刻状态相同。
8、实际编写下来,发现7、认识有问题,这种方式判断周期,有问题,故采用探测100000,若无学生都清醒,则找不到清醒时刻,打印-1。
9、提交AC,此时2016-11-10 22:05,再次做到第一次提交就AC。
附上AC代码,编译环境Dev-C++4.9.9.2
#include <stdio.h>
#include <string.h>
#define maxn 20
struct student{
int a;
int b;
int c;
}stu[maxn];
int behavior[20][20];//记录所有学生的行为(一个周期)
int n;//学生人数
int now[maxn];//当前学生状态
int next[maxn];//下一时刻学生状态
int first[maxn];//第一时刻学生状态
void printnext(){
int i;
for(i=0;i<n;i++)
printf("%d ",next[i]);
printf("\n");
}
void printbehavior(){
int i,j;
for(i=0;i<n;i++){
for(j=1;j<=stu[i].a+stu[i].b;j++){
printf("%d ",behavior[i][j]);
}
printf("\n");
}
}
//记下第一时刻状态,不存在全部清醒,那肯定存在周期性,下一个周期开始时刻与第一时刻状态相同
int main(){
int i,j,k;
int kase=0;
int sleep;
int time;
while(scanf("%d",&n)&&n){
time=1;
memset(behavior,0,sizeof(behavior));
for(i=0;i<n;i++){
scanf("%d%d%d",&stu[i].a,&stu[i].b,&stu[i].c);
for(j=1;j<=stu[i].a;j++)
behavior[i][j]=0;//清醒时刻标记为0
for(;j<=stu[i].a+stu[i].b;j++)
behavior[i][j]=1;//睡觉时刻标记为1
}
//查找学生行为处理
for(i=0;i<n;i++){
next[i]=behavior[i][stu[i].c];
first[i]=next[i];
}
for(i=1;i<=100000;i++){//时刻
sleep=0;
for(j=0;j<n;j++){
now[j]=next[j];//取出上一次下一时刻,成为当前状态
}
for(j=0;j<n;j++){//n个学生,统计睡觉学生数
if(now[j]==1){
sleep++;
}
}
if(sleep==0){//无学生睡觉
time=i;
break;
}
/* //下一个周期判断,若有,则打印-1 ,实施有问题,故将该段代码进行注释
if(i>1){
for(j=0;j<n;j++){
if(now[j]!=first[j])
break;
}
if(j==n){
time=-1;
printf("%d\n",i);
break;
}
}*/
//设置下一时刻学生状态C(2,1)*C(2,1)=4
for(j=0;j<n;j++){
k=(stu[j].c+i)%(stu[j].a+stu[j].b);//下一时刻对应behavior位置
if(k==0)//此举容易漏,根据题中表格可得
k=stu[j].a+stu[j].b;
if(now[j]==0&&behavior[j][k]==0){//now next均清醒
next[j]=0; //清醒
}else if(now[j]==1&&behavior[j][k]==0){//now睡觉 next清醒
next[j]=0;//清醒
}else if(now[j]==1&&behavior[j][k]==1){//now next 均睡觉
next[j]=1;//睡觉
}else if(now[j]==0&&behavior[j][k]==1){//now 清醒 next 睡觉
if(sleep>=(n/2+1)){//睡觉人数超过半数
next[j]=1;//睡觉
}else{
next[j]=0;//不能睡,清醒
}
}
}
}
if(i>100000)
time=-1;
kase++;
printf("Case %d: %d\n",kase,time);
}
return 0;
}