题目说的很乱,我整理一下
所有灯都按绿、橙、红的顺序变化,绿色持续t-5秒,橙色持续5秒,红色持续t秒,第0时刻所有灯都是刚刚变绿。求所有灯再一次变绿的最早时刻
解法:
有一点要明确,所求的最早时刻肯定是所有灯中其中一盏刚刚变绿,否则我们能够找到一个更早的时刻所有灯都是绿的。那么只要枚举所有灯的开始时间,然后再判断此时刻所有灯都是绿色即可。
由于题目要求时刻小于5小时,即使暴力枚举也不过3600*5,再加上判断复杂度,总复杂度为360000*5,应该也能过
当然,可以用堆来优化,这样能够将最坏复杂度至少降低一半
代码:
1# include <cstdio>
2# include <queue>
3# include <cstring>
4using namespace std;
5struct node
6{
7 int i,t;
8 bool operator<(const node &b) const
9 {
10 return t>b.t;
11 }
12 node(int id,int time):i(id),t(time){}
13};
14int loop[101],c,start;
15priority_queue<node> q;
16bool chk(int t)
17{
18 for(int i=0;i<c;i++)
19 if(t%(2*loop[i])>=loop[i]-5) return false;
20 return true;
21}
22void print(int t)
23{
24 printf("%s%d:%s%d:%s%d\n",t/3600<10?"0":"",t/3600,(t%3600)/60<10?"0":"",(t%3600)/60,(t%3600)%60<10?"0":"",(t%3600)%60);
25}
26int main()
27{
28 while(true)
29 {
30 c=0;
31 while(!q.empty()) q.pop();
32 scanf("%d",&loop[c++]);
33 if(!loop[0])
34 {
35 scanf("%d%d",&loop[1],&loop[2]);
36 break;
37 }
38 else
39 {
40 int flag=0;
41 while(loop[c-1])
42 scanf("%d",&loop[c++]);
43 c--;
44 start=0xfffffff;
45 for(int i=0;i<c;i++)
46 if(loop[i]-5<start) start=loop[i]-5;
47 start=0;
48 for(int i=0;i<c;i++)
49 if(2*loop[i]-start<=3600*5) q.push(node(i,2*loop[i]));
50 while(!q.empty()&&!flag)
51 {
52 node top=q.top();
53 q.pop();
54 if(chk(top.t)) flag=top.t;
55 else
56 {
57 top.t+=2*loop[top.i];
58 if(top.t-start<=5*3600) q.push(top);
59 }
60 }
61 if(flag) print(flag-start);
62 else printf("Signals fail to synchronise in 5 hours\n");
63 }
64 }
65 return 0;
66}
67
68