csp 201812_2小明放学(C++)AC代码

本文介绍了一道编程题,涉及智慧城市中红绿灯状态与通行时间的计算。小明需要根据红绿灯的状态和预计的路段时间,估算放学回家所需总时间。代码实现中使用结构体表示红绿灯状态,并通过时间模运算确定信号灯类型,避免超时。
摘要由CSDN通过智能技术生成

题目背景

汉东省政法大学附属中学所在的光明区最近实施了名为“智慧光明”的智慧城市项目。具体到交通领域,通过“智慧光明”终端,可以看到光明区所有红绿灯此时此刻的状态。小明的学校也安装了“智慧光明”终端,小明想利用这个终端给出的信息,估算自己放学回到家的时间。

问题描述

一次放学的时候,小明已经规划好了自己回家的路线,并且能够预测经过各个路段的时间。同时,小明通过学校里安装的“智慧光明”终端,看到了出发时刻路上经过的所有红绿灯的指示状态。请帮忙计算小明此次回家所需要的时间。

输入格式

输入的第一行包含空格分隔的三个正整数 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 ≤ 103
  * 所有测试点保证 n ≤ 105

题目分析

1.由于每个信号灯的类型会随着时间的推移而改变,所以定义信号灯结构体,结构体中包含目前信号灯的类型以及距离下一次信号类型发生改变剩余的时间。
2.问题的核心在于,求出经过t时间后,小明达到某个红绿灯时,红绿灯的类型以及剩余时间。只需要记录好小明到达某个红绿灯时已经使用的时间,即可推算此时红绿灯是什么类型。由于红绿灯是每经过(r+g+y)s就会循环一次,故使用t%(r+g+y)来推断红绿灯类型,如果不这样做会超时
3.需要注意,题目中已经说明,经过一段路所需时间和红绿灯等待时间均最多为106s,道路的段数n最大为105,那么小明回家所需时间最大就有可能是1011,此时已经超过int型数据所能表示的范围,故代码中的整数均直接定义成long long类型。
4.要注意黄灯结束后紧接着是红灯,依然需要等待

AC代码

#include <iostream>
#include <vector>
#include <stdlib.h>
//容易出错的点
//1.由于数据量大,t需要定义成long longl类型
//2.黄灯结束后,还需要紧接着等红灯
//3.小心超时
using namespace std;
//定义结构体,其中包含类型和时间两个信息。
// 另外构造一个函数,用于计算某一个红绿灯经过t时间后是什么类型的灯以及剩余多少时间
typedef struct sig{
    long long type;
    long long time_left;
}sig;
sig next_state(int r, int y, int g, sig p, long long t);
int main() {
    int r, y, g, n, i;
    long long t = 0;
    sig p, ret_sig;
    vector<sig> state;
    cin >> r >> y >> g;
    cin.get();
    cin >> n;
    cin.get();
    for(i=0; i<n; i++){
        cin >> p.type >> p.time_left;
        cin.get();
        state.push_back(p);
    }
    for(i=0; i<n; i++){
        p = state[i];
        if(p.type == 0){
            t+=p.time_left;
        } else{
            ret_sig = next_state(r, y, g, state[i], t);
            if(ret_sig.type == 1){
                t+=ret_sig.time_left;
            }else if(ret_sig.type == 2){
            	t+=ret_sig.time_left;
            	t+=r;
			}
        }
    }
    cout << t;
    return 0;
}
sig next_state(int r, int y, int g, sig p, long long t){
    sig ret_sig;
    int time[4];
    time[1]=r;
    time[2]=y;
    time[3]=g;
    ret_sig.type = p.type;
    ret_sig.time_left = p.time_left;
    if(t>r+g+y){
    	t=t%(r+g+y);//important point to optimize the time cost
	}
    ret_sig.time_left-=t;
    if(ret_sig.time_left<0){
        do{
            ret_sig.type--;
            if(ret_sig.type == 0) ret_sig.type=3;
            ret_sig.time_left+=time[ret_sig.type];
        }while (ret_sig.time_left<0);
    }
    return ret_sig;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值