CCF认证 201812-2小明放学

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/richenyunqi/article/details/86437886

欢迎访问我的CCF认证考试题解目录哦 https://blog.csdn.net/richenyunqi/article/details/83385502

题目描述

CCF认证	201812-2小明放学题目描述

算法设计

本题中红绿灯的变换顺序为

红灯
绿灯
黄灯

可以定义一个长度为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;
}

猜你喜欢

转载自blog.csdn.net/richenyunqi/article/details/86437886