版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/richenyunqi/article/details/86437886
欢迎访问我的CCF认证考试题解目录哦 https://blog.csdn.net/richenyunqi/article/details/83385502
题目描述
算法设计
本题中红绿灯的变换顺序为
可以定义一个长度为3的数组light来存储红灯、绿灯、黄灯时长,令sum为红绿黄灯的总时长。注意由于k=1、2、3 时,分别表示出发时刻,红绿灯状态是红灯、黄灯、绿灯,需要当k==1时,令k=0;当k==3时,令k=2,才能建立起k和数组light的映射关系。
关键是计算出小明到达某一个红绿灯时亮的是那种灯,以及该灯还能亮多长时间。假设初始时刻某一个红绿灯还能亮的时间为b,且该灯在数组light中的下标为a,那么该灯已经点亮的时间为light[a]-b
。假设小明到达该灯时已经用时ans,那么到达该灯时,如果不变灯,该灯已经点亮时间为light[a]-b+ans
。sum为红绿黄灯从红到绿再变黄最后转化到红灯,即红绿灯变换一圈的总时长,那么(light[a]-b+ans)%sum
就表示该红绿灯变换的最后一周的时长。不妨令b=(light[a]-b+ans)%sum
,若b比当前红绿灯时长长,就让b减去当前的红绿灯时长,并令a转向下一个红绿灯,如此反复,直到b比当前红绿灯时长短,那么当前的a就指向小明到达某一个红绿灯时亮的灯,b表示该灯已经点亮的时间。
注意点
要用long long存储数据,int存储会造成数据溢出
C++代码
#include<bits/stdc++.h>
using namespace std;
int main(){
long long light[3],N,a,b,ans=0;
scanf("%lld%lld%lld%lld",&light[0],&light[2],&light[1],&N);
long long sum=light[0]+light[1]+light[2];//sum为红绿灯变换一周的总时长
while(~scanf("%lld%lld",&a,&b)){
if(a==0)//是道路
ans+=b;//时长直接递增
else{//是红绿灯
if(a==1)//将红绿灯标号变为light数组的下标
a=0;
else if(a==3)
a=1;
b=(light[a]-b+ans)%sum;//该红绿灯变换的最后一周的时长
while(b>light[a]){//若b比当前红绿灯时长长
b-=light[a];//减去当前的红绿灯时长
a=(a+1)%3;//转向下一个红绿灯
}
if(a==0)//是红灯
ans+=light[a]-b;//加上红灯剩余时长
else if(a==2)//是黄灯
ans+=light[a]-b+light[0];//加上黄灯剩余时长以及一个红灯时长
}
}
printf("%lld",ans);
return 0;
}