熱門文章

2025年10月23日 星期四

ZeroJudge 解題筆記:f787. 宇辰的閃電

作者:王一哲
日期:2025年10月23日


ZeroJudge 題目連結:f787. 宇辰的閃電

解題想法


這題想要考 C 及 C++ 的結構體 (struct),自訂結構體 Player,用來儲存玩家的姓名、血量、被電時的傷害、下個目標玩家編號、道具清單。由於 Python 的 list 可以儲存不同格式的資料,而且 Python 沒有 struct,所以我直接用 list 儲存玩家資料。

Python 程式碼


使用時間約為 83 ms,記憶體約為 9.6 MB,通過測試。
n, s = map(int, input().split())  # n 位玩家,一開始的目標為 s
players = [[]]  # 玩家資料,開頭放一個空的,資料依序為
                # [名字, 血量, 被電時的傷害, [道具清單], 下個目標玩家編號]
for i in range(1, n+1): # 讀取 1 ~ n 號玩家資料
    line = input().split()
    players.append([line[0], int(line[1]), int(line[2]),
                   line[3:-1], int(line[-1])])
visited = [False]*(1+n)  # 1 ~ n 號玩家是否已被攻擊過
while not visited[s]:  # 如果 s 號玩家還沒有被攻擊過則繼續執行
    visited[s] = True  # s 號玩家已經被攻擊過
    if players[s][2] >= players[s][1]:  # 傷害大於等於血量
        print(f"{players[s][0]:s} dead.")  # 已陣亡
    else:  # 反之
        players[s][1] -= players[s][2]  # 扣血
        for _ in range(players[s][2]):  # 從最後面開始掉道具
            if players[s][3]: players[s][3].pop()
        print(f"{players[s][0]:s} {players[s][1]:d} ", end="")
        print(*players[s][3])
    s = players[s][4]  # 更新目標

因為玩家持有的道具數量等於血量,所以不需要考慮還沒有陣亡但是已經沒有道具的狀況,可以刪掉第15、16行,第18行改成以下這樣。使用時間約為 83 ms,記憶體約為 9.6 MB,通過測試。
print(*players[s][3][:-players[s][2]])


C++ 程式碼


使用時間約為 24 ms,記憶體約為 3.5 MB,通過測試。
#include <iostream>
#include <string>
#include <vector>
using namespace std;

struct Player {  // 玩家
    string name;  // 姓名
    int hp, damage, nxt;  // 血量, 被電時的傷害,下個目標玩家編號
    vector<string> items;  // 道具清單
};

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n, s; cin >> n >> s;  // n 位玩家,一開始的目標為 s
    Player players[n+1];  // 玩家資料,開頭放一個空的
    for(int i=1; i<=n; i++) {  // 讀取 1 ~ n 號玩家資料
        cin >> players[i].name >> players[i].hp >> players[i].damage;
        for(int j=0; j<players[i].hp; j++) {
            string item; cin >> item;
            players[i].items.push_back(item);
        }
        cin >> players[i].nxt;
    }
    bool visited[n+1] = {false};  // 1 ~ n 號玩家是否已被攻擊過
    while(!visited[s]) {  // 如果 s 號玩家還沒有被攻擊過則繼續執行
        visited[s] = true;  // s 號玩家已經被攻擊過
        if (players[s].damage >= players[s].hp) {  // 傷害大於等於血量
            cout << players[s].name << " dead.\n";  // 已陣亡
        } else {  // 反之
            players[s].hp -= players[s].damage;  // 扣血
            for(int i=0; i<players[s].damage; i++) {  // 從最後面開始掉道具
                if (!players[s].items.empty()) players[s].items.pop_back();
            }
            cout << players[s].name << " " << players[s].hp << " ";
            for(int i=0; i<(int)players[s].items.size(); i++) {
                cout << players[s].items[i] << " \n"[i == (int)players[s].items.size()-1];
            }
        }
        s = players[s].nxt;  // 更新目標
    }
    return 0;
}


沒有留言:

張貼留言