题目

题目背景
汉东省政法大学附属中学所在的光明区最近实施了名为“智慧光明”的智慧城市项目。具体到交通领域,通过“智慧光明”终端,可以看到光明区所有红绿灯此时此刻的状态。小明的学校也安装了“智慧光明”终端,小明想利用这个终端给出的信息,估算自己放学回到家的时间。
问题描述
一次放学的时候,小明已经规划好了自己回家的路线,并且能够预测经过各个路段的时间。同时,小明通过学校里安装的“智慧光明”终端,看到了出发时刻路上经过的所有红绿灯的指示状态。请帮忙计算小明此次回家所需要的时间。
输入格式
输入的第一行包含空格分隔的三个正整数 r、y、g,表示红绿灯的设置。这三个数均不超过 106。
输入的第二行包含一个正整数 n,表示小明总共经过的道路段数和路过的红绿灯数目。
接下来的 n 行,每行包含空格分隔的两个整数 k、t。k=0 表示经过了一段道路,将会耗时 t 秒,此处 t 不超过 106;k=1、2、3 时,分别表示出发时刻,此处的红绿灯状态是红灯、黄灯、绿灯,且倒计时显示牌上显示的数字是 t,此处 t 分别不会超过 r、y、g。
输出格式
输出一个数字,表示此次小明放学回家所用的时间。
样例输入
30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出
46
样例说明
小明先经过第一段路,用时 10 秒。第一盏红绿灯出发时是红灯,还剩 5 秒;小明到达路口时,这个红绿灯已经变为绿灯,不用等待直接通过。接下来经过第二段路,用时 11 秒。第二盏红绿灯出发时是黄灯,还剩两秒;小明到达路口时,这个红绿灯已经变为红灯,还剩 11 秒。接下来经过第三、第四段路,用时 9 秒。第三盏红绿灯出发时是绿灯,还剩 10 秒;小明到达路口时,这个红绿灯已经变为红灯,还剩两秒。接下来经过最后一段路,用时 3 秒。共计 10+11+11+9+2+3 = 46 秒。
评测用例规模与约定
有些测试点具有特殊的性质:
前 2 个测试点中不存在任何信号灯。
测试点的输入数据规模:
前 6 个测试点保证 n ≤ 10^3。
* 所有测试点保证 n ≤ 10^5。

思路

我们需要明确,交通灯的状态是循环的,而循环的周期就是( r + y + g ) (r+y+g)(r+y+g),所以求解时可以将经过的时间段对周期取模。【循环问题的通用思路,最好画图理解,这样很清晰。】

image.png
根据交通灯的变化的时间分区间,看取余得到的时间落在哪个区间就可以知道交通灯状态了。

坑:

数据溢出。
题目中有提示,【所有测试点保证 n ≤ 10^5】,题目中可能出现的最大的数为10^610^5=10^11,int型最大表示的数是2147483647≈210^9,表示不了,所以需要用大点的类型,如long long*

代码

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. int r,y,g;//红 黄 绿时间 红——绿——黄
  5. int n;
  6. cin>>r>>y>>g;
  7. cin>>n;
  8. long long sum =0;
  9. while(n--){
  10. int k,t;
  11. int temp;
  12. cin>>k>>t;
  13. switch(k){
  14. case 0:
  15. sum+=t;
  16. break;
  17. case 1://红
  18. if(sum<t){
  19. //到达时还在红灯
  20. sum =t;
  21. }else{
  22. //到达时红灯时间已过 开始循环
  23. temp = (sum-t)%(g+r+y);//周期取模
  24. if(temp>0&&temp<=g){
  25. //在绿灯期
  26. continue;
  27. } else if(g<temp&&temp<=g+y){
  28. //在黄灯
  29. sum+= y-(temp-g)+r;
  30. }else if(g+y<temp&&temp<=g+y+r){
  31. //新一轮红灯
  32. sum+=r -(temp-g-y);
  33. }
  34. }
  35. break;
  36. case 2://黄
  37. if(sum<t){
  38. //到达时还在黄灯
  39. sum =t+r;//黄灯+红灯
  40. }else{
  41. temp = (sum-t)%(g+r+y);//周期取模
  42. if(0<temp&&temp<=r){
  43. //红灯
  44. sum+=r-temp;
  45. }else if(r<temp&&temp<=r+g){
  46. //绿灯
  47. continue;
  48. }else if(r+g<temp&&temp<=r+g+y){
  49. //黄灯
  50. sum+=y-(temp-r-g)+r;
  51. }
  52. }
  53. break;
  54. case 3://绿
  55. if(sum<t){
  56. //到达时还在绿灯
  57. continue;
  58. }else{
  59. temp = (sum-t)%(g+r+y);//周期取模
  60. if(0<temp&&temp<=y){
  61. //黄灯
  62. sum+=y-temp+r;
  63. }else if(y<temp&&temp<=y+r){
  64. //红灯
  65. sum+=r-(temp-y);
  66. }else if(r+y<temp&&temp<=r+g+y){
  67. //绿灯
  68. continue;
  69. }
  70. }
  71. break;
  72. }
  73. }
  74. cout<<sum;
  75. return 0;
  76. }