题目
题目背景 汉东省政法大学附属中学所在的光明区最近实施了名为“智慧光明”的智慧城市项目。具体到交通领域,通过“智慧光明”终端,可以看到光明区所有红绿灯此时此刻的状态。小明的学校也安装了“智慧光明”终端,小明想利用这个终端给出的信息,估算自己放学回到家的时间。 问题描述 一次放学的时候,小明已经规划好了自己回家的路线,并且能够预测经过各个路段的时间。同时,小明通过学校里安装的“智慧光明”终端,看到了出发时刻路上经过的所有红绿灯的指示状态。请帮忙计算小明此次回家所需要的时间。 输入格式 输入的第一行包含空格分隔的三个正整数 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),所以求解时可以将经过的时间段对周期取模。【循环问题的通用思路,最好画图理解,这样很清晰。】
根据交通灯的变化的时间分区间,看取余得到的时间落在哪个区间就可以知道交通灯状态了。
坑:
数据溢出。
题目中有提示,【所有测试点保证 n ≤ 10^5】,题目中可能出现的最大的数为10^610^5=10^11,int型最大表示的数是2147483647≈210^9,表示不了,所以需要用大点的类型,如long long*
代码
#include<iostream>
using namespace std;
int main(){
int r,y,g;//红 黄 绿时间 红——绿——黄
int n;
cin>>r>>y>>g;
cin>>n;
long long sum =0;
while(n--){
int k,t;
int temp;
cin>>k>>t;
switch(k){
case 0:
sum+=t;
break;
case 1://红
if(sum<t){
//到达时还在红灯
sum =t;
}else{
//到达时红灯时间已过 开始循环
temp = (sum-t)%(g+r+y);//周期取模
if(temp>0&&temp<=g){
//在绿灯期
continue;
} else if(g<temp&&temp<=g+y){
//在黄灯
sum+= y-(temp-g)+r;
}else if(g+y<temp&&temp<=g+y+r){
//新一轮红灯
sum+=r -(temp-g-y);
}
}
break;
case 2://黄
if(sum<t){
//到达时还在黄灯
sum =t+r;//黄灯+红灯
}else{
temp = (sum-t)%(g+r+y);//周期取模
if(0<temp&&temp<=r){
//红灯
sum+=r-temp;
}else if(r<temp&&temp<=r+g){
//绿灯
continue;
}else if(r+g<temp&&temp<=r+g+y){
//黄灯
sum+=y-(temp-r-g)+r;
}
}
break;
case 3://绿
if(sum<t){
//到达时还在绿灯
continue;
}else{
temp = (sum-t)%(g+r+y);//周期取模
if(0<temp&&temp<=y){
//黄灯
sum+=y-temp+r;
}else if(y<temp&&temp<=y+r){
//红灯
sum+=r-(temp-y);
}else if(r+y<temp&&temp<=r+g+y){
//绿灯
continue;
}
}
break;
}
}
cout<<sum;
return 0;
}