ZeroJudge H660: 躲避球 (DodgeBall)

阿茂這週假日要去學校和同學一起練習躲避球比賽。躲避球的目標為擲球攻擊對方內場球員,在內場的球員在對方的球來時可以選擇躲開或是接住球,如果擊中身體且沒人接住,則該名球員需移至外場等待。

阿茂在練習躲避球時給自己訂了一個策略:

  1. 原地不動:若落球位置不在阿茂可接球的範圍內則他不會移動。
  2. 接球:若落球位置在可接球範圍且球速夠慢,阿茂會移動到球的位置且接住球。
  3. 閃躲:若落球位置在可接球範圍但球速過快,則阿茂會選擇向球的反方向 (球在阿茂左邊,阿茂就往右邊移動) 移動 15 單位距離;若落球位置與阿茂位置剛好相同,他會往左邊方向閃躲

假設阿茂在位置 100,接球的左右延伸長度為 10 (即 [100–10, 100+100] = [90, 110] 為接球範圍),可接球的球速上限為 10。若落球位置為 99 且球速為 5,則阿茂會選擇接住球且站在位置 99;但若落球位置為 99 且球速為 20,則阿茂會閃躲到 115 (100 + 15) 的位置。

請你利用程式計算阿茂在經過一連串躲避球練習後站著的位置。

範例測資

範例輸入範例輸出
輸入第一列有兩個整數 X、R、V (0 ≤ X ≤ 1000,0 ≤ R ≤ 500,1 ≤ V ≤ 50),分別表示阿茂的位置、接球的左右延伸長度和可接球的球速上限。
第二列有一個整數 N (1 ≤ N ≤ 100) 表示練習的次數,之後有 N 列,每一列有兩個整數 P 和 S (0 ≤ P ≤ 1000,0 ≤ S ≤ 50) 表示每一次的落球位置和球速。同一列任兩個整數間以空白間隔。
輸出一個整數表示最後阿茂所在位置。
100 10 10
3
99 5
97 3
88 4
88
500 80 15
5
400 10
420 5
300 20
395 25
435 18
420
20 10 5
3
30 8
15 2
20 10
0
ZeroJudge H660 範例測資

解題思路

每次紀錄新的 P 和 S 時,先宣告兩個變數 left 和 right,分別代表目前可以接球的左右邊界。

如果今天 P 沒有在 left 和 right 的範圍內,則不需要做任何動作。

如果今天 P 在範圍內,則要先判斷球速 S 是否超過可以承受的球速 V。如果 S <= V,代表可以接球,所以將 X 設定成 P。如果球速過快,則要判斷要往哪邊閃躲,如果今天 P >= X,代表球在右邊,所以要往左閃 X -= 15,這邊使用 >= 是因為題目有說如果 P == X 要往左閃,如果今天球在左邊就是往右閃 X += 15。

最後輸出 X 即可。

範例程式碼-ZeroJudge H660: 躲避球 (DodgeBall)

#include <iostream>
using namespace std;

int main() {
    cin.sync_with_stdio(0);
    cin.tie(0);
    int X, R, V, N;
    cin >> X >> R >> V >> N;
    for (int i = 0; i<N; i++) {
        int P, S, left = X - R, right = X + R;
        cin >> P >> S;
        if (P < left || P > right) continue;
        if (S <= V) {
            X = P;
            continue;
        }
        if (P >= X) X -= 15;
        else X += 15;
    }
    cout << X << "\n";
}

//ZeroJudge H660
//Dr. SeanXD

發佈留言