Processing math: 100%

熱門文章

2025年3月31日 星期一

ZeroJudge 解題筆記:h034. 宴會 (Banquet)

作者:王一哲
日期:2025年3月31日



ZeroJudge 題目連結:h034. 宴會 (Banquet)

解題想法


這題在 Python 可以 itertools.zip_longest 會比較方便。

Python 程式碼


只使用預設工具的寫法,使用時間約為 53 ms,記憶體約為 5.9 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # 餐廳總數
    food = [input().strip() for _ in range(n)]  # 儲存各餐廳的菜單
    m = max([len(f) for f in food])  # 最長的菜單數量
    for i in range(m):  # 處理 m 次
        for j in range(n):  # 印出各家餐廳的菜名
            if i < len(food[j]) and food[j][i].isupper():  # 如果 i 還沒有出界而且 food[j][i] 是大寫字母
                print(food[j][i], end="")  # 印出這個字母
    print()  # 全部跑完再換行

Python 中有一個 zip 工具,用來將數個可以迭代的物件綁在一起輸出,但是 zip 會以這些物件中最短的一個作為輸出的上限,其它較長的部分會被捨去。如果要以最長的物件作為輸出的上限,要用 itertools.zip_longest,長度不夠的部分會補 None。使用時間約為 55 ms,記憶體約為 6 MB,通過測試。
import sys
from itertools import zip_longest

for line in sys.stdin:
    n = int(line)  # 餐廳總數
    food = [input().strip() for _ in range(n)]  # 儲存各餐廳的菜單
    for f in zip_longest(*food):  # 先將 food 拆開成多個一維串列,用 zip_longest 綁在一起依序輸出
        for c in f:  # 依序由 f 讀取各家餐廳的菜名
            if c != None and c.isupper():  # 如果 c 不等於 None 而且是大寫字母
                print(c, end="")  # 印出這個字母
    print()  # 全部跑完再換行


2025年3月30日 星期日

ZeroJudge 解題筆記:h033. 雜訊移除 (Noise)

作者:王一哲
日期:2025年3月30日



ZeroJudge 題目連結:h033. 雜訊移除 (Noise)

解題想法


這題在 Python 可以用 replace 將不要的字元取代成空字串。

Python 程式碼


用 replace 可以取代字串中指定的字元,取代為空字串就可以移除特定字元。使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

def is_palindrome(s):  # 檢查 s 是否為迴文字串
    n = len(s)  # s 的長度 n
    for i in range(n//2):  # 依序檢查從頭尾兩端往中間檢查
        if s[i] != s[n-i-1]: return False  # 如果字元不相同回傳 False
    return True  # 如果可以跑完 for loop,回傳 True

for line in sys.stdin:
    s, n = line.split()  # 要分析的字串 s,要移除的字元 n
    s = s.replace(n, "")  # 將 s 之中的 n 取代為空字串
    print("Yes" if is_palindrome(s) else "No")  # 印出答案

如果不使用 replace,也可以遍歷字串,將要留下來的字元存到另一個空字串裡。使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

def is_palindrome(s):  # 檢查 s 是否為迴文字串
    n = len(s)  # s 的長度 n
    for i in range(n//2):  # 依序檢查從頭尾兩端往中間檢查
        if s[i] != s[n-i-1]: return False  # 如果字元不相同回傳 False
    return True  # 如果可以跑完 for loop,回傳 True

for line in sys.stdin:
    s, n = line.split()  # 要分析的字串 s,要移除的字元 n
    t = ""  # 儲存 s 移除 n 之後的空字串
    for c in s:  # 依序由 s 讀取字元 c
        if c != n: t += c  # 如果 c 不等於 n,接到 t 之後
    print("Yes" if is_palindrome(t) else "No")  # 印出答案


2025年3月29日 星期六

ZeroJudge 解題筆記:g798. 帶動商機 (Business)

作者:王一哲
日期:2025年3月29日



ZeroJudge 題目連結:g798. 帶動商機 (Business)

解題想法


這題按照題目敘述操作陣列即可,不需要用複雜的寫法。

Python 程式碼


使用時間約為 30 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    arr = list(map(int, line.split()))[:-1]  # 讀取一開始的人數,刪掉最後的 0
    m = len(arr)  # 店家數量
    n = int(input())  # 更新 n 天
    for _ in range(n):  # 執行 n 次
        tmp = arr.copy()  # 暫存更新後的人數
        for i in range(m):  # 依序掃過 0 ~ m-1 家店
            if i == 0:  # 最左邊的店家
                if arr[i] > arr[i+1]:  # 如果人數大於右邊的店家
                    tmp[i+1] += arr[i]//10  # 右邊的店家人數增加量
            elif i == m-1:  # 最右邊的店家
                if arr[i] > arr[i-1]:  # 如果人數大於左邊的店家
                    tmp[i-1] += arr[i]//10  # 左邊的店家人數增加量
            else:  # 中間的店家
                if arr[i] > arr[i-1]:  # 如果人數大於左邊的店家
                    tmp[i-1] += arr[i]//20  # 左邊的店家人數增加量
                if arr[i] > arr[i+1]:  # 如果人數大於右邊的店家
                    tmp[i+1] += arr[i]//20  # 右邊的店家人數增加量
        arr, tmp = tmp, arr  # 交換 arr、tmp
    print(*arr)  # 印出答案


2025年3月28日 星期五

ZeroJudge 解題筆記:g797. 洗牌 (Cards)

作者:王一哲
日期:2025年3月28日



ZeroJudge 題目連結:g797. 洗牌 (Cards)

解題想法


這題考陣列操作,可以將陣列先拆開成上、下兩半再合併,或是用另一個陣列儲存洗牌後的資料。

Python 程式碼


寫法1,用串列切片先找出上、下兩半的內容,再合併資料。使用時間約為 26 ms,記憶體約為 3.4 MB,通過測試。
import sys

for line in sys.stdin:
    n, m = map(int, line.split())  # n 張牌,洗牌 m 次
    deck = list(map(int, input().split()))  # 讀取牌面數值
    upp, bot = deck[:n//2], deck[n//2:]  # 分成上、下兩半
    for _ in range(m):  # 執行 m 次
        for i in range(n//2):  # 執行 n//2 次
            deck[2*i] = upp[i]  # 從 upp 及 bot 依序取值放入 deck
            deck[2*i+1] = bot[i]
        upp, bot = deck[:n//2], deck[n//2:]  # 更新 upp、bot
    print(*deck)  # 印出答案

寫法2,滾動串列,將洗牌後的資料先存入另一個串列。使用時間約為 28 ms,記憶體約為 3.4 MB,通過測試。
import sys

for line in sys.stdin:
    n, m = map(int, line.split())  # n 張牌,洗牌 m 次
    deck = list(map(int, input().split()))  # 讀取牌面數值
    for _ in range(m):  # 執行 m 次
        tmp = [0]*n  # 暫存洗牌後的資料
        for i in range(n//2):  # 執行 n//2 次
            tmp[2*i] = deck[i]  # 從 deck 前半取值放入 tmp
            tmp[2*i+1] = deck[n//2 + i]  # 從 deck 後半取值放入 tmp
        deck, tmp = tmp, deck  # 交換 deck、tmp
    print(*deck)  # 印出答案


2025年3月27日 星期四

ZeroJudge 解題筆記:g541. 類題:兔子跳躍(TOIP)

作者:王一哲
日期:2025年3月27日



ZeroJudge 題目連結:g541. 類題:兔子跳躍(TOIP)

解題想法


雖然看起來是g498. 兔子跳躍 (Rabbit)的加強版,但其實用相同的寫法跑迴圈測試是否能走到 d 一定會超時,即使用字典儲存已經跑過的值還是會超時,需要從數學上分析題目才行。如果兩種步數 mn 的最大公因數為 G、最小公倍數為 L,則所有 L+kG,k=0,1,2,3, 的數皆可以用大於等於 0 個 mn 組合而成,若以 m=9n=12 為例,G=3L=36,則
  1. 36=4×9=3×12
  2. 39=3×9+1×12
  3. 42=2×9+2×12
  4. 45=1×9+3×12
  5. 48=0×9+4×12
  6. 51=3×9+2×12
  7. 54=2×9+3×12
  8. 57=1×9+4×12
  9. 60=0×9+5×12=4×9+2×12
  10. 63=3×9+3×12


Python 程式碼


寫法1,根據g498. 兔子跳躍 (Rabbit)的寫法改寫而成,第2筆測資開始超時。
import sys

def solve(m, n, d):  # 自訂函式,測是是否能走到 d
    for i in range(0, d+1, m):  # 依序測試 0, m, 2m, 3m, ...
        if (d-i)%n == 0: return True  # 如果 d-i 可以被 n 整除,能走到 d
    return False  # 如果能跑完 for 迴圈,走不到 d

for line in sys.stdin:
    m, n, q = map(int, line.split())  # 可跳距離 m、n,詢問次數 q
    for d in list(map(int, input().split())):  # 執行 q 次
        print("YES" if solve(m, n, d) else "NO")  # 印出答案

寫法2,根據以上的寫法並改用 map 儲存已經測試過的值,第2筆測資開始超時。
import sys

for line in sys.stdin:
    m, n, q = map(int, line.split())  # 可跳距離 m、n,詢問次數 q
    memo = dict()  # 記憶已經算過的數據
    def solve(d):  # 自訂函式,測是是否能走到 d
        if d in memo: return memo[d]
        for i in range(0, d+1, m):  # 依序測試 0, m, 2m, 3m, ...
            if (d-i)%n == 0:
                memo[d] = True
                return True  # 如果 d-i 可以被 n 整除,能走到 d
        memo[d] = False
        return False  # 如果能跑完 for 迴圈,走不到 d
    for d in list(map(int, input().split())):  # 執行 q 次
        print("YES" if solve(d) else "NO")  # 印出答案

2025年3月26日 星期三

ZeroJudge 解題筆記:g498. 兔子跳躍 (Rabbit)

作者:王一哲
日期:2025年3月26日



ZeroJudge 題目連結:g498. 兔子跳躍 (Rabbit)

解題想法


這題測資不大,用 for 迴圈依序檢測每一個值就能過關。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    m, n, d = map(int, line.split())  # 可跳距離 m、n,目標距離 d
    def solve():  # 自訂函式,測是是否能走到 d
        for i in range(0, d+1, m):  # 依序測試 0, m, 2m, 3m, ...
            if (d-i)%n == 0: return True  # 如果 d-i 可以被 n 整除,能走到 d
        return False  # 如果能跑完 for 迴圈,走不到 d
    print("YES" if solve() else "NO")  # 印出答案


C++ 程式碼


使用時間約為 2 ms,記憶體約為 84 kB,通過測試。
#include <cstdio>
using namespace std;

bool solve(int m, int n, int d) {  // 自訂函式,測是是否能走到 d
    for(int i=0; i<=d; i+=m) {  // 依序測試 0, m, 2m, 3m, ...
        if ((d-i)%n == 0) return true;  // 如果 d-i 可以被 n 整除,能走到 d
    }
    return false;  // 如果能跑完 for 迴圈,走不到 d
}

int main() {
    int m, n, d;  // 可跳距離 m、n,目標距離 d
    while(scanf("%d %d %d", &m, &n, &d) != EOF) {
        if (solve(m, n, d)) printf("YES\n");  // 印出答案
        else printf("NO\n");
    }
    return 0;
}


2025年3月25日 星期二

ZeroJudge 解題筆記:g497. 電梯 (Elevator)

作者:王一哲
日期:2025年3月25日



ZeroJudge 題目連結:g497. 電梯 (Elevator)

解題想法


注意:電梯一開始在 1 樓。

Python 程式碼


使用時間約為 46 ms,記憶體約為 3.8 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # 升降次數
    arr = [1] + list(map(int, input().split()))  # 停留的樓層,開頭加上 1
    tot = 0  # 耗電量
    for i in range(n):  # 依序掃過 0 ~ n-1
        d = arr[i+1] - arr[i]  # 樓層變化
        if d > 0: tot += 3*d  # 上升一層耗 3 度電
        else: tot -= 2*d  # 下降一層耗 2 度電
    print(tot)  # 印出答案


C++ 程式碼


使用時間約為 2 ms,記憶體約為 96 kB,通過測試。
#include <cstdio>
using namespace std;

int main() {
    int n;  // 升降次數
    while(scanf("%d", &n) != EOF) {
        int pre = 1, now, tot = 0;  // 原來的樓層,預設值為 1;現在的樓層;耗電量
        for(int i=0; i<n; i++) {  // 執行 n 次
            scanf("%d", &now);  // 讀取現在的樓層
            int d = now - pre;  // 樓層變化
            if (d > 0) tot += 3*d;  // 上升一層耗 3 度電
            else tot -= 2*d;  // 下降一層耗 2 度電
            pre = now;  // 更新 pre
        }
        printf("%d\n", tot);  // 印出答案
    }
    return 0;
}


2025年3月24日 星期一

ZeroJudge 解題筆記:g496. 彗星列車 (Comet)

作者:王一哲
日期:2025年3月24日



ZeroJudge 題目連結:g496. 彗星列車 (Comet)

解題想法


注意:這題每組測資有多筆測試資料,而且每筆測試資料之間似乎有空行,如果用 Python 解題要忽略空行,否則會出錯。

Python 程式碼


使用時間約為 19 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    if len(line.strip()) == 0: continue  # 忽略空行
    a, s = map(int, line.split())
    if s%a == 0: print(s//a)
    else: print(s//a + 1)


C++ 程式碼


用 cmath 函式庫的 ceil,先計算 s/a 的值再取 ceil,計算時及回傳值是浮點數,要再轉回整數,但是這樣無法通過第8筆測資。
#include <cstdio>
#include <cmath>  // for ceil
using namespace std;

int main() {
    int a, s;
    while(scanf("%d %d", &a, &s) != EOF) {
        printf("%d\n", int(ceil((float)s/(float)a)));
    }
    return 0;
}

還是回來用標準寫法,使用時間約為 6 ms,記憶體約為 96 kB,通過測試。
#include <cstdio>
using namespace std;

int main() {
    int a, s;
    while(scanf("%d %d", &a, &s) != EOF) {
        if (s%a == 0) printf("%d\n", s/a);
        else printf("%d\n", s/a + 1);
    }
    return 0;
}


2025年3月23日 星期日

ZeroJudge 解題筆記:g006. 密碼備忘錄 (Password)

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



ZeroJudge 題目連結:g006. 密碼備忘錄 (Password)

解題想法


這題我用字典計數,再用 cmp_to_key 或 lambda function 自訂比較式。

Python 程式碼


使用時間約為 24 ms,記憶體約為 3.9 MB,通過測試。
import sys
from collections import Counter
from functools import cmp_to_key

def mycmp(a, b):  # (key, val)
    if a[1] > b[1]: return -1  # 如果 a[1] > b[1],a 往前放
    elif a[1] < b[1]: return 1  # 如果 a[1] < b[1],a 往後放
    else:  # 如果 a[1] == b[1]
        if a[0] < b[0]: return -1  # 如果 a[0] < b[0],a 往前放
        elif a[0] > b[0]: return 1  # 如果 a[0] > b[0],a 往後放
        else: return 0

for s in sys.stdin:
    cnt = Counter(s.strip())  # 刪除 s 結尾的 \n,用 Counter 計算各字母數量
    ans = sorted([(k, v) for k, v in cnt.items()], key=cmp_to_key(mycmp))  # 排序
    print("".join([k for k, v in ans]))  # 將 k 取出組成字串再印出


2025年3月22日 星期六

ZeroJudge 解題筆記:g005. 倒置文章 (Inversion)

作者:王一哲
日期:2025年3月22日



ZeroJudge 題目連結:g005. 倒置文章 (Inversion)

解題想法


這題考字串處理,從頭開始依序讀取字串的內容,先暫存內容到另一個字串,如果讀到 + 或 - 再結算之前暫存的內容,儲存到最後要輸出的字串之中。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

for s in sys.stdin:
    s = s.strip()  # 刪除讀到的字串結尾的 \n
    rev = False  # 是否反轉,預設為否
    a, t = "", ""  # a 儲存答案,t 儲存反轉字串
    for c in s:  # 依序由 s 讀取字元 c
        if c == '+':  # 如果 c 是 +
            a += t; t = ""  # 結算之前儲存的 t,將 t 接到 a 之後再清空 t
            rev = False  # 順向
        elif c == '-':  # 如果 c 是 -
            a += t; t = ""  # 結算之前儲存的 t,將 t 接到 a 之後再清空 t
            rev = True  # 反向
        else:  # 如果 c 是其它字元
            if rev: t = c+t  # 如果目前是反向,將 c 接到 t 之前
            else: a += c  # 如果目前是順向,將 c 接到 a 之後
    a += t  # 最後再結算一次 t
    print(a)  # 印出答案


2025年3月21日 星期五

ZeroJudge 解題筆記:g004. 社區熱門度 (Popularity)

作者:王一哲
日期:2025年3月21日



ZeroJudge 題目連結:g004. 社區熱門度 (Popularity)

解題想法


處理這種類型的題目時,我習慣在周圍或是最後面多加一些資料,可以避免在四方位檢查時出界。

Python 程式碼


可以先將答案存入另一個二維串列,使用時間約為 19 ms,記憶體約為 3.4 MB,通過測試。
import sys

for line in sys.stdin:
    m, n = map(int, line.split())  # 地圖 m*n
    grid = [list(map(int, input().split())) + [0] for _ in range(m)]  # 地圖資料,最後加上 0
    grid.append([0]*(n+1))  # 最後加上 n+1 個 0
    ans = [grid[r][:-1] for r in range(m)]  # 儲存答案用的二維串列
    for r in range(m):  # 依序掃過每一格
        for c in range(n):
            if grid[r][c] != 0: continue  # 如果 (r, c) 這個不等於 0,找下一格
            cnt, tot = 0, 0  # 右下左上 4 格非 0 的格子數量,熱門度加總
            for dr, dc in ((0, 1), (1, 0), (0, -1), (-1, 0)):  # 檢查周圍 4 格
                v = grid[r+dr][c+dc]
                if v != 0:
                    cnt += 1; tot += v
            if tot != 0: ans[r][c] = tot//cnt  # 如果 tot 不等於 0,更新 ans[r][c]
    for row in ans: print(*row)  # 印出答案

2025年3月20日 星期四

ZeroJudge 解題筆記:f820. 極限運動 (Sports)

作者:王一哲
日期:2025年3月20日



ZeroJudge 題目連結:f820. 極限運動 (Sports)

解題想法


這題在左、右兩側各加上超出題目範圍的極大值,在向左、右找終點時可以避免出界。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # 地圖上有 n 個位置
    hs = [1000] + list(map(int, input().split())) + [1000]  # 各位置高度,兩端加上 1000
    s = int(input())  # 起點 s
    e = s  # 終點 e 設定為 s
    if s == 1:  # 只能往右滑
        while hs[e] >= hs[e+1]: e += 1  # 向右滑直到右側高度大於左側為止
    elif s == n:  # 只能往左滑
        while hs[e] >= hs[e-1]: e -= 1  # 向左滑直到左側高度大於右側為止
    else:  # 可以向左或向右滑
        if hs[e-1] < hs[e+1]:  # 左側較低,向左滑
            while hs[e] >= hs[e-1]: e -= 1  # 向左滑直到左側高度大於右側為止
        else:  # 右側較低,向右滑
            while hs[e] >= hs[e+1]: e += 1  # 向右滑直到右側高度大於左側為止
    print(e)  # 印出終點


2025年3月19日 星期三

ZeroJudge 解題筆記:f819. 圖書館 (Library)

作者:王一哲
日期:2025年3月19日



ZeroJudge 題目連結:f819. 圖書館 (Library)

解題想法


因為這題不確定要輸出的資料數量,在 C++ 用 vector 儲存資料會比較方便。

Python 程式碼


使用時間約為 27 ms,記憶體約為 3.8 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # n 本書
    books = []  # 逾期書的編號
    fine = 0  # 罰款金額
    for _ in range(n):  # 讀取 n 行資料
        b, d = map(int, input().split())  # 書的編號 b、天數 d
        if d > 100:  # 逾期
            books.append(b)  # b 加入 books
            fine += (d-100)*5  # 超過 100 天每天罰 5 元
    if not books: print(0)  # 如果 books 沒有資料,印出 0
    else:  # 反之,印出 books 排序後的內容及 fine
        print(*sorted(books)); print(fine)


2025年3月18日 星期二

ZeroJudge 解題筆記:f818. 物競天擇 (Survival)

作者:王一哲
日期:2025年3月18日



ZeroJudge 題目連結:f818. 物競天擇 (Survival)

解題想法


這題考排序,需要自訂排序的比較式,因為比較式不像前一題那麼複雜,我是用 lambda function 寫比較式。

Python 程式碼


使用時間約為 22 ms,記憶體約為 3.7 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # 小獅子數量 n
    hs = list(map(int, input().split()))  # 小獅子身高 h
    ws = list(map(int, input().split()))  # 小獅子體重 w
    hw = [(h, w) for h, w in zip(hs, ws)]  # 將 hs, ws 合併成二維串列,資料為 (h, w)
    hw.sort(key = lambda x : x[0]*x[1])  # 將 hw 依照 h*w 由小到大排序
    print(*hw[0])  # 最小值在首項


2025年3月17日 星期一

ZeroJudge 解題筆記:g796. 檔案分類 (Files)

作者:王一哲
日期:2025年3月17日



ZeroJudge 題目連結:g796. 檔案分類 (Files)

解題想法


這題用字典計數比較方便,如果用 Python 可以用 defaultdict 就不需要檢查 key 值是否存在,但是在輸出答案時要先按照 key 值由小到大排序;如果用 C++ 的 map,本來就會按照 key 值由小到大排序,直接輸出就好。

Python 程式碼


使用時間約為 50 ms,記憶體約為 3.7 MB,通過測試。
import sys
from collections import defaultdict

for line in sys.stdin:
    n = int(line)  # 檔案數量
    cnt = defaultdict(int)  # 計數器
    for _ in range(n):  # 執行 n 次
        cnt[int(input().strip()[3:])//10] += 1  # 讀取字串,去掉 \n,取後 3 位轉成 int
    for k, v in sorted(cnt.items()): print(k, v)  # 印出答案


C++ 程式碼


使用時間約為 3 ms,記憶體約為 364 kB,通過測試。
#include <iostream>
#include <string>
#include <map>
using namespace std;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n;  // 檔案數量
    string s;  // 檔案編號
    while(cin >> n) {
        map<int, int> cnt;  // 計數器
        for(int i=0; i<n; i++) {  // 執行 n 次
            cin >> s;  // 讀取編號
            cnt[stoi(s.substr(3))/10]++;  // s 取後 3 位轉成 int
        }
        for(auto it : cnt) cout << it.first << " " << it.second << "\n";  // 印出答案
    }
    return 0;
}


2025年3月16日 星期日

ZeroJudge 解題筆記:f707. 幸運 7 (Lucky Seven)

作者:王一哲
日期:2025年3月17日



ZeroJudge 題目連結:f707. 幸運 7 (Lucky Seven)

解題想法


這題考排序,需要自訂排序的比較式。

Python 程式碼


使用時間約為 45 ms,記憶體約為 3.9 MB,通過測試。
import sys
from functools import cmp_to_key

def mycmp(a, b):
    if a%7 == 0 and b%7 != 0: return -1  # a 可以被 7 整除但 b 不行,a 往前放
    elif a%7 != 0 and b%7 == 0: return 1  # a 不行被 7 整除但 b 可以,a 往後放
    elif a%7 == 0 and b%7 == 0:  # a、b 都可以被 7 整除
        if a%70 > b%70: return -1  # a 除以 70 的餘數比較大,a 往前放
        elif a%70 < b%70: return 1  # a 除以 70 的餘數比較小,a 往後放
        else: return 0
    else:  # a、b 都不行被 7 整除
        if a%77 < b%77: return -1  # a 除以 77 的餘數比較小,a 往前放
        elif a%77 > b%77: return 1  # a 除以 77 的餘數比較大,a 往後放
        else: return 0

for line in sys.stdin:
    arr = list(map(int, line.split()))[:-1]  # 轉成整數串列並去掉最後一項
    arr.sort(key = cmp_to_key(mycmp))  # 排序
    print(arr[0])  # 最大值在首項


2025年3月15日 星期六

ZeroJudge 解題筆記:f706. 時區 (Zone)

作者:王一哲
日期:2025年3月15日



ZeroJudge 題目連結:f706. 時區 (Zone)

解題想法


這題需要注意輸出的格式,分、秒如果只有個位數,前面需要補0。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

d = 5400  # 1h30' = 5400"
a = 129600  # 36h = 129600"
for line in sys.stdin:
    h, m, s, t = map(int, line.split())  # 時、分、秒、向東或西移動幾個時區
    if t == -24 or t == 24:  # 特例,向東或西繞一圈回到原時區
        print(f"{h:d}:{m:02d}:{s:02d}")  # 印出讀到的數值即可,分和秒要有2位數
        continue  # 繼續找下一組
    s += h*3600 + m*60  # 先全部換成秒
    s += t*d  # 依照移動的時區加或減秒數
    s = (s+a)%a  # 處理可能回到前一天或進到下一天的問題
    h = s//3600  # 計算小時
    s %= 3600  # 計算小時之後剩下的秒數
    m = s//60  # 計算分鐘
    s %= 60  # 計算分鐘之後剩下的秒數
    print(f"{h:d}:{m:02d}:{s:02d}")  # 印出答案,分和秒要有2位數


2025年3月14日 星期五

ZeroJudge 解題筆記:f515. 英文縮寫 (Abbreviation)

作者:王一哲
日期:2025年3月14日



ZeroJudge 題目連結:f515. 英文縮寫 (Abbreviation)

解題想法


我會先將讀取的字串先全部轉換成大寫字母,這樣在檢查特例及組合答案時會比較方便。

Python 程式碼


使用時間約為 40 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    # 刪除最後的 \n,轉成大寫,用空格分開,轉成串列
    line = list(line.strip().upper().split())
    a = ""  # 儲存答案用的空字串
    for s in line:  # 從 line 依序讀取字串 s
        if s == "FOR": a += "4"  # 先處理特例
        elif s == "TO": a += "2"
        elif s == "AND": a += "n"
        elif s == "YOU": a += "u"
        else: a += s[0]  # 如果不是特例,a 加上 s 開頭的字元
    print(a)  # 印出答案


2025年3月13日 星期四

ZeroJudge 解題筆記:f514. 拼字遊戲 (Spelling)

作者:王一哲
日期:2025年3月13日



ZeroJudge 題目連結:f514. 拼字遊戲 (Spelling)

解題想法


因為 Python 的字串不能用索引值修改某個字元,轉成串列會比較方便。儲存答案的串列 ans,雖然有些資料是整數、有些是字元,但是串列的資料格式可以混搭,還是可以儲存。而 C++ 的 vector 只能儲存同一種格式的資料,要先將找到的字元位置轉成字串再存入 ans 之中。

Python 程式碼


使用時間約為 19 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    s = [""] + list(line.strip())  # 將 line 去掉結尾的 \n 轉成串列,開頭加上空格以配合題目的編號從 1 開始
    t = list(sys.stdin.readline().strip())  # 將讀取到的字串去掉結尾的 \n 轉成串列
    ans = []  # 答案
    for c in t:  # 由 t 依序讀取字元 c
        if c in s:  # 如果 c 在 s 之中
            p = s.index(c)  # 找出 c 在 s 中的位置
            ans.append(p)  # p 加入 ans
            s[p] = ""  # s[p] 改為空字串
        else:  # 如果 c 不在 s 之中
            ans.append("X")  # 字串 X 加入 ans
    print(*ans)  # 印出 ans


2025年3月12日 星期三

ZeroJudge 解題筆記:f513. 舉旗遊戲 (Flag)

作者:王一哲
日期:2025年3月12日



ZeroJudge 題目連結:f513. 舉旗遊戲 (Flag)

解題想法


這題如果在周圍加上 0 作為哨兵,可以在檢查周圍 8 格時不需要考慮是否出界,程式碼會比較簡單。由於 Python 的串列索引值 -1 會對應到最後一項,不需要圍一整圈,只要圍最右側、最下方即可。

Python 程式碼


使用時間約為 39 ms,記憶體約為 3.4 MB,通過測試。
import sys

for line in sys.stdin:
    m, n = map(int, line.split())  # 地圖 m*n
    grid = [list(map(int, input().split())) + [0] for _ in range(m)]  # 地圖,最後加上 0 作為哨兵
    grid.append([0]*(n+1))  # 最後加上 n+1 個 0 作為哨兵
    tot = 0  # 淘汰人數
    for r in range(m):  # 依序檢查每個人
        for c in range(n):
            a = grid[r][c]  # 這個人的顏色 a
            out = True  # 是否淘汰
            for dr, dc in ((0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)):  # 檢查周圍 8 格
                nr, nc = r+dr, c+dc  # 要檢查的格子 (nr, nc)
                if grid[nr][nc] == a:  # 如果 (nr, nc) 的顏色與 a 相同
                    out = False; break  # 不會淘汰,中止迴圈
            if out: tot += 1  # 如果淘汰了,tot 加 1
    print(tot)


2025年3月11日 星期二

ZeroJudge 解題筆記:f443. 商品擺設 Merchandise

作者:王一哲
日期:2025年3月11日



ZeroJudge 題目連結:f443. 商品擺設 Merchandise

解題想法


寫法1,先找到最左側隔板的位置 pre,設定最大值 imax 為 0、最小值 imin 為 1000,接著再繼續往右找,如果這格是商品就更新 imax、imin 及對應的位置 pmax、pmin;再次遇到隔板時,將 pmax、pmin 的商品對調,重置 imax、imin;重複以上的過程直到讀完貨架資料為止。

寫法2,先設定前一個隔板的位置 pre 為 -1,依序掃過每一格,如果在第 i 格遇到隔板而且 pre 不等於 -1,再用 index、max、min 及串列切片找區間最大值、最小值位置。效率會比寫法1差一點。

Python 程式碼


寫法1,使用時間約為 18 ms,記憶體約為 3.4 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # 商品數量
    val = list(map(int, input().split()))  # 商品銷售量
    key = list(map(int, input().split()))  # 商品編號
    i, pre = 0, -1  # 目前正在檢查的位置,前一個隔板的位置
    while val[i] != -1 and i < n: i += 1  # 繼續執行直到遇到第一個隔板或出界為止
    if i < n: pre = i  # 如果還沒有出界,pre 設定為 i
    imax, imin = 0, 1000  # 商品銷售量最大值、最小值
    pmax, pmin = 0, 0  # 商品銷售量最大值、最小值對應的編號
    i += 1  # i 加 1,接下來找下一格
    while i < n:  # 繼續執行直到出界為止
        if val[i] == -1:  # 如果是隔板
            if i - pre > 1:  # 如果這個隔板與前一個隔板距離超過一格
                val[pmax], val[pmin] = val[pmin], val[pmax]  # 交換商品銷售量
                key[pmax], key[pmin] = key[pmin], key[pmax]  # 交換商品編號
                imax, imin = 0, 1000  # 重置商品銷售量最大值、最小值
            pre = i  # pre 設定為 i
        else:  # 如果是商品
            if val[i] > imax:  # 如果是新的最大值
                imax, pmax = val[i], i  # 更新 imax, pmax
            if val[i] < imin:  # 如果是新的最小值
                imin, pmin = val[i], i  # 更新 imin, pmin
        i += 1  # i 加 1
    print(*key)  # 印出最後的商品編號

2025年3月10日 星期一

ZeroJudge 解題筆記:f442. 老鷹抓小雞 Eagle

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



ZeroJudge 題目連結:f442. 老鷹抓小雞 Eagle

解題想法


我將交換小雞、老鷹編號的部分拆開來寫,這樣會比較容易看懂。

Python 程式碼


使用時間約為 27 ms,記憶體約為 3.8 MB,通過測試。
import sys

for line in sys.stdin:
    n = int(line)  # 小雞數量
    arr = list(map(int, input().split()))  # 小雞編號
    e = int(input())  # 老鷹編號
    q = int(input())  # 遊戲回合
    tar = list(map(int, input().split()))  # 每回合抓到的小雞編號
    for t in tar:  # 從 tar 依序讀取編號
        i = arr.index(t)  # t 在 arr 中的索引值
        c = t  # 暫存下一回合老鷹編號
        arr[i] = e  # 更新 arr
        e = c  # 更新 e
    print(*arr)  # 印出答案


2025年3月9日 星期日

ZeroJudge 解題筆記:f441. 評分系統 Score

作者:王一哲
日期:2025年3月9日



ZeroJudge 題目連結:f441. 評分系統 Score

解題想法


因為 Python 一次讀取一行資料,所以在 Python 程式碼中我是用 zip 將正確答案及學生的答案綁在一起讀取。在 C++ 中則是一次讀取一個整數,遇到空格就停下來,可以每次讀一個學生的答案計分。

Python 程式碼


使用時間約為 20 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    n, s = map(int, line.split())  # 題數 n,每題分數 s
    ans = list(map(int, input().split()))  # 答案
    m = int(input())  # 待批改試卷數量
    for _ in range(m):  # 執行 m 次
        cnt = 0  # 答對題數
        stu = list(map(int, input().split()))  # 學生的答案
        for a, b in zip(ans, stu):  # 由 ans 及 stu 依序讀取資料
            if a == b: cnt += 1  # 如果 a 等於 b,cnt 加 1
        print(cnt*s)  # 印出分數


2025年3月8日 星期六

ZeroJudge 解題筆記:f375. 神奇肥料 Fertilizer

作者:王一哲
日期:2025年3月8日



ZeroJudge 題目連結:f375. 神奇肥料 Fertilizer

解題想法


按照題目指定規則寫條件即可。注意:每天都可以檢查花的高度,即使是每 9 天的休假日,如果花的高度大於等於顧客要求的高度,仍然可以印出天數。

Python 程式碼


使用時間約為 39 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    s, e, a = map(int, line.split())  # 起始高度 s、目標高度 e、耐性 a
    h, d = 0, 0  # 增加的高度,天數
    while True:
        s += h; d += 1  # 更新 s 及 d
        if d%11 == 0 and s < e:  # 每隔 11 天而且 s 小於 e
            a -= 1  # a 減 1
            if a == 0:  # 如果 a 等於 0
                print("unsalable"); break  # 印出 unsalable 並中止迴圈
        if s >= e:  # 如果 s 大於等於 e
            print(d); break  # 印出天數並中止迴圈
        else:  # 如果 s 小於 e
            if d%9 == 0 or d%10 == 0: h = 0  # 每隔 9 天或 10 天,h 為 0
            elif d%3 == 0: h = s//3  # 每隔 3 天且不是休假日,h 為 s//3
            else: h = s//10  # 其它天,h 為 s//10


2025年3月7日 星期五

ZeroJudge 解題筆記:f374. 分組 Grouping

作者:王一哲
日期:2025年3月7日



ZeroJudge 題目連結:f374. 分組 Grouping

解題想法


這題在 Python 我是用 enumerate 搭配字串切片 [::-1] 反向讀取字元,在 C++ 則是用索引值從字串中讀取字元。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
import sys

for line in sys.stdin:
    n, s = line.split()  # 將 line 分割成每組人數 n、戰力 s
    n = int(n)  # 將 n 轉成整數
    idx, imax = 0, 0  # 最大戰力組別、戰力
    group, tot = 1, 0  # 目前的組別、戰力
    for i, c in enumerate(s[::-1]):  # 從 s 最後面往前讀取
        tot += int(c)  # 將 c 轉成整數加到 tot
        if (i+1)%n == 0 or i == len(s)-1:  # 如果 (i+1) 可以被 n 整除或是 i 等於 len(s)-1,檢查小組戰力
            if tot >= imax:  # 如果 tot 大於等於 imax
                imax = tot  # imax 更新為 tot
                idx = group  # idx 更新為 group
            tot = 0; group += 1  # tot 歸零,group 加 1
    print(f"{idx:d} {imax:d}")  # 印出答案


2025年3月6日 星期四

ZeroJudge 解題筆記:f345. 新手練習題—陣列

作者:王一哲
日期:2025年3月6日



ZeroJudge 題目連結:f345. 新手練習題—陣列

解題想法


這題很簡單,有很多不同的寫法,我盡量列出已知的寫法。

Python 程式碼


寫法 1


先將資料轉成整數儲存到串列中,再用索引值反過來輸出,使用時間約為 1.6 s,記憶體約為 132.6 MB,通過測試。
n = int(input())  # 陣列長度
arr = list(map(int, input().split()))  # 陣列
for i in range(n-1, -1, -1):  # 用索引值反向輸出
    print(arr[i], end="\n" if i == 0 else " ")

寫法 2


直接用字串儲存到串列中,再用索引值反過來輸出,使用時間約為 1.4 s,記憶體約為 106.8 MB,通過測試。
n = int(input())  # 陣列長度
arr = list(input().split())  # 陣列
for i in range(n-1, -1, -1):  # 用索引值反向輸出
    print(arr[i], end="\n" if i == 0 else " ")

寫法 3


先將資料轉成整數儲存到串列中,用串列切片將串列反過來,最後用開箱運算子印出串列內容。使用時間約為 0.9 s,記憶體約為 140.3 MB,通過測試。
_ = int(input())  # 陣列長度,用不到
arr = list(map(int, input().split()))  # 陣列
arr = arr[::-1]  # 用串列切片將陣列反過來
print(*arr)  # 用開箱運算子印出陣列內容

寫法 4


可以將上方的程式碼第3、4行合併。使用時間約為 0.9 s,記憶體約為 147.9 MB,通過測試。
_ = int(input())  # 陣列長度,用不到
arr = list(map(int, input().split()))  # 陣列
print(*arr[::-1])  # 用串列切片將陣列反過來,再用開箱運算子印出陣列內容

寫法 5


將資料轉成整數存到串列中,用 reversed 將串列反過來,最後用開箱運算子印出串列內容。使用時間約為 0.9 s,記憶體約為 140.3 MB,通過測試。
_ = int(input())  # 陣列長度,用不到
print(*reversed(list(map(int, input().split()))))

寫法 6


將寫法 3 改用字串格式,使用時間約為 0.6 s,記憶體約為 109.3 MB,通過測試。
_ = int(input())  # 陣列長度,用不到
arr = list(input().split())  # 陣列
arr = arr[::-1]  # 用串列切片將陣列反過來
print(*arr)  # 用開箱運算子印出陣列內容

寫法 7


將寫法 4 改用字串格式,使用時間約為 0.6 s,記憶體約為 116.7 MB,通過測試。
_ = int(input())  # 陣列長度,用不到
arr = list(input().split())  # 陣列
print(*arr[::-1])  # 用串列切片將陣列反過來,再用開箱運算子印出陣列內容

寫法 8


將寫法 5 改用字串格式,使用時間約為 0.6 s,記憶體約為 109.1 MB,通過測試。
_ = int(input())  # 陣列長度,用不到
print(*reversed(list(input().split())))

寫法 9


如果使用字串格式,還可以用 join 將串列內容用空格連接成一個很長的字串一起輸出,使用時間約為 0.2 s,記憶體約為 120.5 MB,通過測試。
_ = int(input())  # 陣列長度,用不到
print(" ".join(reversed(list(input().split()))))


2025年3月5日 星期三

ZeroJudge 解題筆記:f341. 5.閱讀順序(Reading)

作者:王一哲
日期:2025年3月5日



ZeroJudge 題目連結:f341. 5.閱讀順序(Reading)

解題想法


這題考字串操作,在 Python 用字串切片很好寫,在 C++ 最好是使用 string 函式庫的 substr 及 algorithm 函式庫的 reverse 會比較好寫。

Python 程式碼


使用時間約為 25 ms,記憶體約為 3.3 MB,通過測試。
def solve(s, x):
    if s == x: return s  # 特例,直接回傳 s
    n, m = len(s), len(x)  # s、x 的長度
    c = s.find(x)  # 翻轉軸於 s 的索引值
    if c == 0:  # x 在開頭
        ri = s[m:]  # 取 x 右側的子字串
        return ri[::-1] + s[:m]  # 將 ri 放在左側並反向,加上 x 左側的子字串
    elif c+m == n:  # x 在結尾
        le = s[:c]  # 取 x 左側的子字事
        return s[c:] + le[::-1]  # x 右側的子字串,加上 le 放在右側並反向 
    else:  # x 在中間
        le, ri = s[:c], s[c+m:]  # 取 x 左、右兩側的子字串
        return ri[::-1] + s[c:c+m] + le[::-1]  # ri 放到左側並反向,le 放在右側並反向

s = input().strip()  # 原來的字串
x = input().strip()  # 翻轉軸
print(solve(s, x))  # 呼叫 solve 並印出答案


2025年3月4日 星期二

ZeroJudge 解題筆記:f340. 4.俄羅斯方塊 (Tetris)

作者:王一哲
日期:2025年3月4日



ZeroJudge 題目連結:f340. 4.俄羅斯方塊 (Tetris)

解題想法


這題要先寫出各種指令對應的操作,還要檢查方塊是否在邊界使方塊無法旋轉,寫起來很容易出錯。

Python 程式碼


使用時間約為 24 ms,記憶體約為 5.1 MB,通過測試。
# 方向:0 朝右,1 朝下,2 朝左,3 朝上
def bottom(x, y, d):  # 檢查是否已觸底,輸入錨點座標 (x, y),方向 d
    if d == 3: return y >= n-1  # 朝上,回傳 y 是否大於等於 n-1
    else: return y+1 >= n-1  # 其它方向,回傳 y+1 是否大於等於 n-1
    
def zero(x, y, d):  # 指令 0,方向 d,向下移一格
    return x, y+1, d

def one(x, y, d):  # 指令 1,輸入錨點座標 (x, y),方向 d,向右、向下移一格
    # 如果「方向朝右、下、上且 x+1 小於 m-1」或是「方向朝左且 x 小於 m-1」,可以向右移一格
    if (d in (0, 1, 3) and x+1 < m-1) or (d == 2 and x < m-1): x += 1
    return x, y+1, d

def two(x, y, d):  # 指令 2,輸入錨點座標 (x, y),方向 d,向左、向下移一格
    # 如果「方向朝下、左、上且 x-1 大於 0」或是「方向朝右且 x 大於 0」,可以向左移一格
    if (d in (1, 2, 3) and x-1 > 0) or (d == 0 and x > 0): x -= 1
    return x, y+1, d

def three(x, y, d):  # 指令 3,輸入錨點座標 (x, y),方向 d,置底
    if d == 3: return x, n-1, d  # 朝上,錨點 y = n-1
    else: return x, n-2, d  # 其它方向,錨點 y = n-2

def four(x, y, d):  # 指令 4,輸入錨點座標 (x, y),方向 d,右旋
    if d == 2 and x == m-1: d = 2  # 朝左且 x 等於 m-1,不能右旋
    elif d == 0 and x == 0: d = 0  # 朝右且 x 等於 0,不能右旋
    else: d = (d+1)%4  # 右旋
    if bottom(x, y, d): return x, y, d  # 如果已經觸底,回傳 x, y, d
    return x, y+1, d  # 否則回傳 x, y+1, d

### 初始化 ###
m, n = map(int, input().split())  # 畫面寬度 m、高度 n
s = int(input())  # 指令數量 s
arr = list(map(int, input().split()))  # 指令
if m%2 == 1: x = (m+1)//2 - 1  # 如果 m 是奇數
else: x = m//2 - 1  # 如果 m 是偶數
y = 0  # 初位置 y 座標
d = 1  # 方向朝下
### 依照指令改變方塊的位置及方向 ###
for a in arr:  # 依序由 arr 讀取指令 a
    if a == 0: x, y, d = zero(x, y, d)  # 指令 0
    elif a == 1: x, y, d = one(x, y, d)  # 指令 1
    elif a == 2: x, y, d = two(x, y, d)  # 指令 2
    elif a == 3: x, y, d = three(x, y, d); break  # 指令 3,執行完畢後中止迴圈
    else: x, y, d = four(x, y, d)  # 指令 4
    if bottom(x, y, d): break  # 如果已經觸底中止迴圈
### 畫出最後的地圖 ###
grid = [[0]*m for _ in range(n)]  # 地圖
if d == 0:  # 朝右
    grid[y-1][x] = grid[y][x] = grid[y+1][x] = grid[y][x+1] = 1
elif d == 1:  # 朝下
    grid[y][x-1] = grid[y][x] = grid[y][x+1] = grid[y+1][x] = 1
elif d == 2:  # 朝左
    grid[y-1][x] = grid[y][x] = grid[y+1][x] = grid[y][x-1] = 1
else:  # 朝上
    grid[y][x-1] = grid[y][x] = grid[y][x+1] = grid[y-1][x] = 1
for g in grid: print(*g, sep='')  # 印出地圖


2025年3月3日 星期一

ZeroJudge 解題筆記:f339. 3.下雪的日子(Snow)

作者:王一哲
日期:2025年3月3日



ZeroJudge 題目連結:f339. 3.下雪的日子(Snow)

解題想法


有兩個要特別注意的地方:
  1. Python 才有的問題,輸入的資料可能是長度等於 1 的字串,要跳過這些字串不處理。
  2. 暢通的道路資料可能起點、終點相同,要跳過這些資料不處理。


Python 程式碼


使用時間約為 25 ms,記憶體約為 4.4 MB,通過測試。
import sys
from functools import cmp_to_key

def mycmp(a, b):  # 依照起點由小到大排序,若起點相同,依照終點由大到小排序
    if a[0] < b[0]: return -1
    elif a[0] > b[0]: return 1
    else:
        if a[1] > b[1]: return -1
        elif a[1] < b[1]: return 1
        else: return 0
        
for line in sys.stdin:
    if len(line) <= 1: continue  # 如果字串長度小於等於 1,繼續讀下一行
    n, m = map(int, line.split())  # 道路總長度 n, m 筆道路資訊
    pa = [list(map(int, input().split())) for _ in range(m)]  # 暢通道路
    pa.sort(key = cmp_to_key(mycmp))  # 排序
    ans = []  # 答案
    if pa[0][0] > 0: ans.append((0, pa[0][0]))  # 檢測第0段及 0 之間是否不通
    ri = pa[0][1]  # 目前檢測的右端點
    for s, e in pa[1:]:  # 由 pa[1] 開始依序讀取暢通道路起點 s、終點 e
        if s == e: continue  # 如果 s 等於 e,沒用的資料,繼續找下一段
        if s > ri: ans.append((ri, s))  # 如果 s 大於 ri,中間有不通的地方,(ri, s) 加入 ans
        ri = max(ri, e)  # 更新 ri,取 ri 及 e 較大者
    if n > ri: ans.append((ri, n))  # 最後的右端點與 n 之間不通
    if ans:  # 如果 ans 有內容才印出 ans
        for a in ans: print(*a)


2025年3月2日 星期日

ZeroJudge 解題筆記:f149. 3. 炸彈偵測器 (Detector)

作者:王一哲
日期:2025年3月2日



ZeroJudge 題目連結:f149. 3. 炸彈偵測器 (Detector)

解題想法


因為在檢查周圍 8 格時可能會出界,造成 index error,所以我習慣在每列最後、最下面或四周加上 0。

Python 程式碼


使用時間約為 19 ms,記憶體約為 3.4 MB,通過測試。
m, n = map(int, input().split())  # 地圖 m*n
grid = [list(map(int, input().split())) + [0] for _ in range(m)]  # 地圖,結尾加上 0 作為哨兵
grid.append([0]*(n+1))  # 地圖最後加上 n+1 個 0 作為哨兵
bomb = set()  # 炸彈位置
found = set()  # 找到的炸彈位置
test = ((-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1))  # 要檢測的周圍 8 格
for r in range(m):  # 依序掃過 r = 0 ~ m-1
    for c in range(n):  # 依序掃過 c = 0 ~ n-1
        if grid[r][c] == 1: bomb.add((r, c))  # 找到炸彈,(r, c) 加入 bomb
        elif grid[r][c] == 5:  # 偵測器
            other = False  # 周圍 8 格是否有其它的偵測器
            tmp = []  # 暫存周圍 8 格的炸彈位置
            for dr, dc in test:  # 依序檢測周圍 8 格
                nr, nc = r+dr, c+dc  # 要檢測的格子 (nr, nc)
                if grid[nr][nc] == 5:  # 其它的偵測器
                    other = True  # other 設定為 True
                    break  # 中止迴圈
                elif grid[nr][nc] == 1:  # 找到炸彈,(nr, nc) 加入 tmp
                    tmp.append((nr, nc))
            if not other:  # 如果周圍 8 格沒有其它的偵測器
                for (nr, nc) in tmp:  # 從 tmp 依序讀取找到的炸彈位置
                    found.add((nr, nc))  # (nr, nc) 加入 found
print(f"{len(found):d} {len(bomb)-len(found):d}")  # 印出答案


2025年3月1日 星期六

ZeroJudge 解題筆記:f148. 2. 定向越野 (Orienteering)

作者:王一哲
日期:2025年3月1日



ZeroJudge 題目連結:f148. 2. 定向越野 (Orienteering)

解題想法


如果使用 Python,可以將目標點的字母、x 座標、y 座標組成數組,再加到串列之中,排序時會用數組最前面的資料為基準。如果使用 C++,要先自訂結構體,將目標點的字母、x 座標、y 座標存到結構體之中,再放入陣列,排序時可以用 lambda function 指定要以結構體之中的哪一項資料排序。

Python 程式碼


使用時間約為 26 ms,記憶體約為 3.3 MB,通過測試。
w, h = map(int, input().split())  # 地圖 w 列、h 欄
n = int(input())  # 要找 n 個目標
target = []  # 目標,(字母, x, y)
for r in range(w):  # 執行 w 次
    line = list(input().split())  # 讀取一行資料
    for c, s in enumerate(line):  # 從 line 依序讀取字元 s,索引值 c
        if s != '0': target.append((s, r, c))  # 如果 s 不等於 0,(s, r, c) 加入 target
target.sort()  # 依照開頭的字母排序
if len(target) < n:  # 如果 target 數量小於 n
    print("Mission fail.")  # 印出 Mission fail.
else:  # 任務成功,印出 target 前 n 個的座標
    for (_, r, c) in target[:n]:
        print(f"{r:d} {c:d}")