csp 小明放學(C++的坑)

題目背景
  漢東省政法大學附屬中學所在的光明區最近實施了名爲“智慧光明”的智慧城市項目。具體到交通領域,通過“智慧光明”終端,可以看到光明區所有紅綠燈此時此刻的狀態。小明的學校也安裝了“智慧光明”終端,小明想利用這個終端給出的信息,估算自己放學回到家的時間。
問題描述
  一次放學的時候,小明已經規劃好了自己回家的路線,並且能夠預測經過各個路段的時間。同時,小明通過學校裏安裝的“智慧光明”終端,看到了出發時刻路上經過的所有紅綠燈的指示狀態。請幫忙計算小明此次回家所需要的時間。
輸入格式
  輸入的第一行包含空格分隔的三個正整數 r、y、g,表示紅綠燈的設置。這三個數均不超過 10^6
  輸入的第二行包含一個正整數 n,表示小明總共經過的道路段數和路過的紅綠燈數目。
  接下來的 n 行,每行包含空格分隔的兩個整數 k、t。k=0 表示經過了一段道路,將會耗時 t 秒,此處 t 不超過 10^6;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

思路:題意爲給出小明出發時看到的各個路口的紅綠燈的顏色和通過每條道路的時間,求其回家總共用的時間。這題只需要簡單模擬即可,在第一題的基礎上只需要寫出當小明經過now秒後,到達某個路口時,現在紅綠燈的顏色是什麼?以及還剩多少秒?

這題的坑有兩個,首先數據量很大,如果用int只能得60分(不知道爲什麼考試得了40分。。。),一共通過n個路口,n ≤ 10^5,並且紅綠燈的持續時間 r、y、g,這三個數均不超過 10^6 。想象極端情況10^5個用例全部需要等待10 ^6次方秒那麼總共需要的時間sum數量級爲10 ^11(INT_MAX=2147483647, 10^10量級),所以爲了保險起見,直接用ide的替換功能把int替換成long long。其次總共需要的時間sum數量巨大,紅綠燈在這個時間內經歷了很多輪的變化,一輪指的是經歷過紅綠黃三種顏色的燈,紅綠燈是循環的,經過紅綠黃一輪的時間後,紅綠燈的顏色還是當前的顏色,剩餘的時間減去了一輪經過的時間,所以在求紅綠燈狀態時,先把現在的時間sum = sum%(r+g+y)。如果不這樣的話會超時,我的程序只得了70分。

改過上面的兩個地方最後得到了100分,所以這題的教訓是要注意數據的規模,仔細想想規律

#include "iostream"
#include "climits"
using namespace std;

long long r, y, g;
long long n;

long long time1(long long light, long long time){//計算狀態燈爲light,剩餘時間爲time時通過的時間
    if (light == 0) //一條道路
        return time;
    if (light == 1) //紅燈
        return time;
    if (light == 2) //黃燈
        return time + r;
    if (light == 3) //綠燈
        return 0;
}

long long get_next_light(long long light){//狀態爲light信號燈的下一行信號燈是什麼
    if(light == 1)//紅色
        return 3;
    if(light == 2)//黃燈
        return 1;
    if (light ==3)//綠燈
        return 2;
}

long long get_next_time(long long light){//該信號燈的下一個信號燈的時間
    if(light == 1)//紅燈
        return g;
    if(light == 2)//黃燈
        return r;
    if(light == 3)//綠燈
        return y;
}

long long get_time(long long light, long long time, long long now){//初始時刻爲light,time的狀態過了now秒後是什麼情況
    if(light == 0){//道路
        return time;
    } 
    if(now==0){
        return time1(light, time);
    }
    while(now>0){
        if(now>=time){
            now = now - time; 
            time = get_next_time(light);
            light = get_next_light(light);
        }
        else{
            time = time - now;
            now = 0;
        }
    }
    return time1(light, time);
}

int main(){
    cin >> r >> y >> g;
    cin >> n;
    long long sum = 0;
    for (long long i = 0; i < n;i++){
        long long k, t;
        cin >> k >> t;
        sum += get_time(k, t, sum%(r+y+g));
    }
    cout << sum << endl;
    //system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章