这个题即给定睡眠和醒着的周期以及开始时在周期的多少分钟,
如果打算睡时发现一半以上的人都没睡那就不睡了,再过一个醒着的周期再看
(我觉得只要坚持了之后醒着的人就会一直比睡了的人多,,希望我没想错)
#include<iostream>
#include<fstream>
#include<vector>
#include<map>
#include<iomanip>
using namespace std;
// 用一个课程最长的情况来跳出循环
const int LL = 1000;
// 课程类用静态变量记录有多少人以及当前睡着的人数
struct Course
{
static int student, sleepingStu;
};
// 静态成员赋初值
int Course::student = 0;
int Course::sleepingStu = 0;
// 学生类继承课程
struct Student :public Course
{
// 每一个学生的周期记录
int aware, sleep, startTime;
bool sleepstate, keepOn;
Student(int a, int b, int c) :aware(a), sleep(b), startTime(c)
{
if (startTime <= aware) sleepstate = 0; else { sleepstate = 1; sleepingStu++; }
keepOn = 0;
}
// 重载输入
friend istream& operator >> (istream& in, Student it) {
in >> it.aware >> it.sleep >> it.startTime; return in;
}
// 这个其实思路有点类似与Qt的Timer
void sleepOrNot(int now,int lastSecSleep) {
// 如果开始坚持直接跳出
if (keepOn) { return; }
// 没过一个睡眠周期后醒来
else if ((now - 1 + startTime) % (aware + sleep) == 1) {
if (sleepstate)sleepingStu--, sleepstate = 0;
}
// 过一个清醒周期
else if ((now - 1 + startTime) % (aware + sleep)- aware == 1) {
// 因为每个学生是同时判断人数决定睡或不睡,所以要避免过程中睡着学生的改变,所以传参来保证同时
if (student - lastSecSleep > lastSecSleep)
{
keepOn = 1;
if (sleepstate)sleepingStu--, sleepstate = 0;
}
else if (!sleepstate) { sleepingStu++; sleepstate = 1; }
}
}
};
int main()
{
freopen("in.txt", "r", stdin);
freopen("my_ans.txt", "w", stdout);
int n; int round = 0;
while (cin >> n) {
if (n == 0) break;
cout << "case " << ++round << ": ";
Student::student = n;
vector<Student> stu; for (int i = 0; i < n; i++) { int a, b, c; cin >> a >> b >> c; stu.push_back({ a,b,c }); };
// 判断是否一开始就没人睡
bool goodclass = 1; for (auto i : stu) if (i.sleepstate == 1) goodclass = 0;
if (goodclass)
{ cout << "1\n"; continue; }
int now = 1;
while (true)
{
now++;
if (now > LL) { now = -1; break; }
vector<Student>::iterator it = stu.begin();
int lastSecSleep = it->sleepingStu;
while (it != stu.end()) { it->sleepOrNot(now, lastSecSleep); it++; }
if (!Student::sleepingStu) break;
}
cout << now << endl;
}
return 0;
}
这个题我一开始的思路就是取余循环周期,但这样的效率太低
中间有几个Debug的点:
1. for(auto i: stu) 是创建一个临时变量对stu里的数据拷贝,在成员函数中修改后不会记录到stu对象的数据成员
2. 学生是同时判断的,用静态成员函数能保证共享修改,但是不能在循环时使先进入循环的影响后续,所以要传参他们判断时睡的人
3. 判断是否开始时就没人睡,否则如果now 从1开始遍历可能对初始状态进行改变
本题我的思路大致是这样,与Debug里的几万组数据对比仍会有不对的answer, 但大多还是能AC
仅记录一下自己的思路,后续再改...
好吧...看了一下别人的代码,我怎么能把问题复杂化成这样...
大佬永远是简化问题,小白是把简单问题复杂化还觉得自己写了内容...
本题即利用数组记录状态更新即可,本质没当数组走完一整个周期则回到醒着的时候,或者当走完一个醒着的周期发现不能睡则归零
#include<iostream>
using namespace std;
// 用一个大数跳出循环
const int LL = 1000;
// 存储对应周期
int awake[11], sleep[11], timer[11];
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("my_ans.txt", "w", stdout);
int n,round = 0;
while (cin >> n) {
if (n == 0) break;
cout << "Case " << ++round << ": ";
int sec = 1;
for (int i = 0; i < n; i++)cin >> awake[i] >> sleep[i] >> timer[i];
for (sec = 1; sec <= LL ; sec++)
{
int wake = 0; // 每一次重新计算醒着的人
for (int i = 0; i < n; i++)
{
if (awake[i] >= timer[i]) wake++;
}
if (wake == n) { cout << sec << endl; break; }
for (int i = 0; i < n; i++) {
// 走完一次循环或不睡
if (timer[i] == awake[i] + sleep[i] || timer[i] == awake[i] && wake >= n - wake)
timer[i] = 0;
timer[i]++;
}
// 跳出的结果
if (sec == LL) { cout << "-1" << endl; break; }
}
}
return 0;
}