【CSP试题回顾】201812-2-小明放学(优化)

CSP-201812-2-小明放学

关键点:红绿灯处理逻辑

红绿灯逻辑处理部分是本题最关键的一环,它根据小明到达每个红绿灯时的具体情况,决定是否需要等待以及等待多久。

1. 遇到红灯 (k == 1)

  • 当前时间在红灯时间内:如果currentTime(从最近一次红灯开始后经过的时间)小于红灯剩余时间t,则小明需要等待直到红灯结束,等待时间为t - currentTime
  • 当前时间在绿灯时间内:如果currentTimett + g之间,小明不需要等待,可以直接通过。
  • 当前时间在黄灯时间内:如果currentTimet + gt + g + y之间,小明需要等待黄灯结束后再等一个完整的红灯时间,总等待时间为t + g + y - currentTime + r
  • 当前时间再次回到红灯时间:如果currentTimet + g + yt + r + y + g之间,即经过一整轮红绿灯周期后再次遇到红灯,小明需要等待的时间为t + r + y + g - currentTime

2. 遇到黄灯 (k == 2)

  • 当前时间在黄灯时间内:如果currentTime小于黄灯剩余时间t,则小明需要先等待黄灯结束,再等一个完整的红灯时间,总等待时间为t - currentTime + r
  • 当前时间在红灯时间内:如果currentTimett + r之间,小明需要等待红灯结束,等待时间为t + r - currentTime
  • 当前时间在绿灯时间内:如果currentTimet + rt + r + g之间,小明可以直接通过,无需等待。
  • 当前时间再次回到黄灯时间:如果currentTimet + r + gt + r + y + g之间,即经过一整轮红绿灯周期后再次遇到黄灯,小明需要等待的时间为t + r + y + g - currentTime + r

3. 遇到绿灯 (k == 3)

  • 当前时间在绿灯时间内:如果currentTime小于绿灯剩余时间t,小明可以直接通过,无需等待。
  • 当前时间在黄灯时间内:如果currentTimett + y之间,小明需要等待黄灯结束后再等一个完整的红灯时间,总等待时间为t + y - currentTime + r
  • 当前时间在红灯时间内:如果currentTimet + yt + y + r之间,小明需要等待红灯结束,等待时间为t + y + r - currentTime
  • 当前时间再次回到绿灯时间:如果currentTimet + y + rt + r + y + g之间,即经过一整轮红绿灯周期后再次遇到绿灯,小明可以直接通过,无需等待。

注意:本部分代码的条件,分支语句有一定程度上的冗余,但是为了理解方便保留了这些冗余,读者可以自行优化。

解题思路

  1. 初始化和输入: 首先,通过cin >> r >> y >> g >> n;读入红绿灯的三种状态时间(红、黄、绿灯时间)和小明经过的道路段数(包括红绿灯)。这里r, y, g分别代表红、黄、绿灯持续的时间,n代表总共的路段数。

  2. 循环处理每个路段: 接下来,对于小明将要经过的每一个路段(包括实际的道路和红绿灯),用一个循环进行处理。在循环中,使用cin >> k >> t;读入当前路段的类型(k)和耗时或剩余时间(t)。

  3. 计算时间: 对于每个路段,根据k的值来判断是实际的道路还是遇到的红绿灯:

    • 如果k == 0,表示是一段实际的道路,直接累加该路段的耗时ttimeSpend(总耗时)上。
    • 如果k为1、2、3,则分别表示遇到红灯、黄灯、绿灯,需要根据当前的currentTime(当前时间对红绿灯周期的取余结果)来判断小明到达该灯时的状态,并据此决定是否需要等待。
  4. 红绿灯逻辑处理:

    • 对于红灯(k == 1):如果在红灯时到达,则判断当前时间是否在红灯时间内,如果是,则需等待直到红灯结束;如果当前时间在绿灯或黄灯时间内,则不用等待;若当前时间处于红灯的第二个周期,则同样需要等待。
    • 对于黄灯(k == 2):逻辑类似,只是需要在黄灯结束后等待一个完整的红灯时间。
    • 对于绿灯(k == 3):如果到达时灯是绿的,则无需等待;如果是黄灯或红灯,则需要等待直到绿灯开始。
  5. 输出结果: 循环结束后,输出timeSpend,即小明回家所需的总时间。

完整代码

#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <stack>
#include <string>
using namespace std;

long long r, y, g, n, k, t, timeSpend, currentTime;

int main()
{
    cin >> r >> y >> g >> n;
    for (size_t i = 0; i < n; i++)
    {
        cin >> k >> t;
        if (k == 0)
            timeSpend += t;
        else
        {
            currentTime = timeSpend % (r + y + g);
            if (k == 1) // red light
            {
                if (0 <= currentTime && currentTime < t) // red
                    timeSpend += (t - currentTime);
                else if (t <= currentTime && currentTime < t + g) {} // green
                else if (t + g <= currentTime && currentTime < t + g + y) // yellow
                    timeSpend += (t + g + y - currentTime + r);
                else if (t + g + y <= currentTime && currentTime < t + r + y + g) // red
                    timeSpend += (t + r + y + g - currentTime);//
            }
            else if (k == 2) // yellow light;
            {
                if (0 <= currentTime && currentTime < t) // yellow
                    timeSpend += (t - currentTime + r);
                else if (t <= currentTime && currentTime < t + r) // red
                    timeSpend += (t + r - currentTime);
                else if (t + r <= currentTime && currentTime < t + r + g) {} // green
                else if (t + r + g <= currentTime && currentTime < t + r + y + g) // yellow
                    timeSpend += (t + r + y + g - currentTime + r);
            }
            else if (k == 3) // green light
            {
                if (0 <= currentTime && currentTime < t) {} // green                                                 // green
                else if (t <= currentTime && currentTime < t + y) // yellow
                    timeSpend += (t + y - currentTime + r);
                else if (t + y <= currentTime && currentTime < t + y + r) // red
                    timeSpend += (t + y + r - currentTime);
                else if (t + y + r <= currentTime && currentTime < t + r + y + g) {} // green
            }
        }
    }
    cout << timeSpend;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值