熱門文章

2025年2月20日 星期四

ZeroJudge 解題筆記:e973. 3. 滿意度調查 (Survey of Satisfaction)

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



ZeroJudge 題目連結:e973. 3. 滿意度調查 (Survey of Satisfaction)

解題想法


這題用 map 和自訂排序用的比較式,寫起來會很方便。

Python 程式碼


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

def mycmp(a, b):
    if a[0] > b[0]: return -1  # 如果 a[0] 大於 b[0],a 往前放
    elif a[0] < b[0]: return 1  # 如果 a[0] nc 於 b[0],a 往後放
    else:  # 如果 a[0] 等於 b[0]
        if a[1] < b[1]: return -1  # 如果 a[0] 小於 b[0],a 往前放
        elif a[1] > b[1]: return 1  # 如果 a[0] 大於 b[0],a 往後放
        else: return 0

cnt = Counter(list(input().strip()))  # 讀取字串,去掉結尾的 \n,轉成 list,傳入計數器
output = sorted([(val, key) for key, val in cnt.items()], key=cmp_to_key(mycmp))  # 讀取 cnt 的資料並排序
for i in range(len(output)):  # 印出答案
    print(output[i][1], end='\n' if i == len(output)-1 else ' ')


2025年2月19日 星期三

ZeroJudge 解題筆記:e972. 1. 貨幣轉換 (Currency)

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



ZeroJudge 題目連結:e972. 1. 貨幣轉換 (Currency)

解題想法


這題的第三筆測資是用 \r 換行,用 Python 解題反而很麻煩。

Python 程式碼


因為第3筆測資是用 \r 分隔資料,這樣寫過不了。
import re
ori = int(input())  # 原有的金額
rem = 0  # 剩下的金額
data = re.split(r"\s+", input())
cost = int(data[0])
if data[1] == 'T': rem = ori - cost  # 台幣
elif data[1] == 'U': rem = ori / 30.9 - cost  # 美金
elif data[1] == 'J': rem = ori / 0.28 - cost  # 日幣
elif data[1] == 'E': rem = ori / 34.5 - cost  # 歐元
if 0 < rem < 0.05: rem = 0.00  # 若 rem 為正數且小於 0.05,改成 0.00 
if rem < 0: print("No Money")  # 如果 rem 小於 0,印出 No Money
else: print(f"{data[1]:s} {rem:.2f}")  # 剩出幣制及餘額


改成這樣才能通過。使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
data = input().replace('\r', ' ')  # 將 \r 換成空格
try:
    n = input()
except:  # 為了處理第 3 筆測資,\r 會使游標在換行後移到上一行
    data, a, b = data.split()  # 目的地幣值 b
else:
    a, b = n.split()
    
ori = int(data)  # 原有的金額
cost = int(a)  # 花費
rem = 0  # 剩下的金額

if b == 'T': rem = ori - cost  # 台幣
elif b == 'U': rem = ori / 30.9 - cost  # 美金
elif b == 'J': rem = ori / 0.28 - cost  # 日幣
elif b == 'E': rem = ori / 34.5 - cost  # 歐元
if 0 < rem < 0.05: rem = 0.00  # 若 rem 為正數且小於 0.05,改成 0.00 
if rem < 0: print("No Money")  # 如果 rem 小於 0,印出 No Money
else: print(f"{b:s} {rem:.2f}")  # 剩出幣制及餘額


2025年2月18日 星期二

ZeroJudge 解題筆記:e971. 2. 梗圖著色 (Coloring)

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



ZeroJudge 題目連結:e971. 2. 梗圖著色 (Coloring)

解題想法


只要記錄前一個 1 的位置就好,不需要用到 queue。

Python 程式碼


使用時間約為 41 ms,記憶體約為 3.4 MB,通過測試。
m, n = map(int, input().split())  # 圖的高度 m、寬度 n
for _ in range(m):  # 讀取 m 行資料
    arr = list(map(int, input().split()))  # 一行圖形資料
    pre = -1  # 前一個 1 的位置,預設為 -1
    for i, a in enumerate(arr):  # 由 arr 依序讀取數值 a、索引值 i
        if a == 1:  # 如果 a 等於 1
            if pre != -1:  # 如果 pre 不等於 -1
                for j in range(pre+1, i): arr[j] = 1 # 將 [pre+1, i-1] 之間都設定為 1
                pre = -1  # pre 重設為 -1
            else: pre = i  # 如果 pre 等於 -1,pre 設定為 i
    print(*arr)  # 印出這行塗色後的結果


C++ 程式碼


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

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int m, n; cin >> m >> n;  // 圖的高度 m、寬度 n
    for(int i=0; i<m; i++) {  // 讀取 m 行資料
        int arr[n] = {0}, pre = -1;  // 一行圖形資料,前一個 1 的位置,預設為 -1
        for(int j=0, a; j<n; j++) {  // 讀取 n 個數值 a
            cin >> a; arr[j] = a;  // 讀取圖形資料
            if (a == 1) {  // 如果 a 等於 1
                if (pre != -1) {  // 如果 pre 不等於 -1
                    for(int k=pre+1; k<j; k++) arr[k] = 1;  // 將 [pre+1, i-1] 之間都設定為 1
                    pre = -1;  // pre 重設為 -1
                } else pre = j;  // 如果 pre 等於 -1,pre 設定為 j
            }
        }
        for(int j=0; j<n; j++) cout << arr[j] << " \n"[j == n-1];  // 印出這行塗色後的結果
    }
    return 0;
}


2025年2月17日 星期一

ZeroJudge 解題筆記:e970. 1. 粉專抽獎 (Lucky Draw)

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



ZeroJudge 題目連結:e970. 1. 粉專抽獎 (Lucky Draw)

解題想法


按照題目敘述的規則計算就好。

Python 程式碼


使用時間約為 24 ms,記憶體約為 4.3 MB,通過測試。
n = int(input())  # 留言量 n
arr = [0] + list(map(int, input().split()))  # n 個隨機數字
b = arr[-1]  # arr 最後一項是基數 b
tot = 0  # 索引值對應到之隨機數字加總
for i in range(1, n+1):  # 依序測試 1 ~ n
    if i%b == 1: tot += arr[i]  # 如果 i 除以 b 的餘數等於 1,將 arr[i] 加到 tot
m = tot%n  # 中獎留言索引值
if m == 0: m = n  # 如果 m 等於 0,最後一則留言中獎,m 改為 n
print(f"{m:d} {arr[m]:d}")  # 印出 m 及 arr[m]


C++ 程式碼


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

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n; cin >> n;  // 留言量 n
    int arr[n+1] = {0};  // n 個隨機數字,為了配合題目的索引值,前面多一個 0
    for(int i=1; i<=n; i++) cin >> arr[i];
    int b = arr[n], tot = 0;  // arr 最後一項是基數 b,索引值對應到之隨機數字加總
    for(int i=1; i<=n; i++) {  // 依序測試 1 ~ n
        if (i%b == 1) tot += arr[i];  // 如果 i 除以 b 的餘數等於 1,將 arr[i] 加到 tot
    }
    int m = tot%n;  // 中獎留言索引值
    if (m == 0) m = n;  // 如果 m 等於 0,最後一則留言中獎,m 改為 n
    cout << m << " " << arr[m] << "\n";  // 印出 m 及 arr[m]
    return 0;
}


2025年2月16日 星期日

ZeroJudge 解題筆記:e969. 大吃大喝 (Big eater)

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



ZeroJudge 題目連結:e969. 大吃大喝 (Big eater)

解題想法


這題要很注意輸出的內容,很容易弄錯一些細節。

Python 程式碼


使用時間約為 20 ms,記憶體約為 3.3 MB,通過測試。
n, m, k = map(int, input().split())
t = 0
food = ("eats an Apple pie", "drinks a Corn soup")
imin = (32, 55)

if n < imin[k]:
    print("Wayne can't eat and drink.")
else:
    while n >= imin[k]:
        n -= imin[k]
        print(f"{t:d}: Wayne {food[k]:s}, and now he ", end="")
        if n == 0: print(f"doesn't have money.")
        elif n == 1: print(f"has 1 dollar.")
        else: print(f"has {n:d} dollars.")
        k = (k+1)%2
        t += m


2025年2月15日 星期六

ZeroJudge 解題筆記:e948. 基礎代謝率 (BMR Calculation)

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



ZeroJudge 題目連結:e948. 基礎代謝率 (BMR Calculation)

解題想法


這題考輸出格式,要輸出小數點後 2 位,如果是用 C++ 可以用 printf 會比較方便。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
n = int(input())  # 人數
for _ in range(n):  # 執行 n 次
    g, a, h, w = map(int, input().split())  # 性別、年齡、身高、體重
    if g == 1:  # 男
        print(f"{13.7*w + 5.0*h - 6.8*a + 66:.2f}")
    else:  # 女
        print(f"{9.6*w + 1.8*h - 4.7*a + 655:.2f}")


C++ 程式碼


使用 iomanip 函式庫的 setprecison 固定輸出的小數點位數。使用時間約為 2 ms,記憶體約為 352 kB,通過測試。
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n; cin >> n;  // 人數
    for(int i=0; i<n; i++) {  // 執行 n 次
        int g, a, h, w; cin >> g >> a >> h >> w;  // 性別、年齡、身高、體重
        float bmr;
        if (g == 1) bmr = 13.7*w + 5.0*h - 6.8*a + 66.0;  // 男
        else bmr = 9.6*w + 1.8*h - 4.7*a + 655.0;  // 女
        cout << fixed << setprecision(2) << bmr << "\n";
    }
    return 0;
}

2025年2月14日 星期五

ZeroJudge 解題筆記:e841. P8. 幽靈寶藏(Treasure)

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



ZeroJudge 題目連結:e841. P8. 幽靈寶藏(Treasure)

解題想法


操作有以下 2 種
  1. 在連續的數個藏寶箱內放入 $S$ 枚硬幣。
  2. 使連續的數個藏寶箱內的硬幣價值變為 $S$ 倍,包括事後放入的硬幣
所以操作時不需要考慮先加或是先乘,寫起來會簡單很多。

Python 程式碼


測資很大,第18筆測資開始超時。
n, m = map(int, input().split())  # n 個寶箱,編號 1 ~ n;m 次操作
add = [0]*(n+2)  # 各個寶箱硬幣增加的數量
mul = [1]*(n+2)  # 各個寶箱硬幣乘上的倍數
div = [1]*(n+2)  # 各個寶箱硬幣除掉的倍數
for _ in range(m):  # 讀取 m 次操作
    p, q, r, s = map(int, input().split())  # 範圍 [p, q],操作種類 r,數量 s
    if r == 1:  # 操作是 1
        add[p] += s  # 編號 p 硬幣加 s
        add[q+1] -= s  # 編號 q+1 硬幣減 s
    elif r == 2:  # 操作是 2
        mul[p] *= s  # 編號 p 硬幣乘上的倍數乘以 s
        div[q+1] *= s  # 編號 q+1 硬幣除掉的倍數乘以 s
# end of for loop
idx, imax = 0, 0  # 最大值的寶箱編號,最大值
cur_val, cur_mul = 0, 1  # 目前的硬幣數量,目前乘上的倍數
for i in range(1, n+1):  # 更新各個寶箱的硬幣數量
    cur_mul = cur_mul * mul[i] // div[i]  # 更新 cur_mul
    cur_val += add[i]  # 更新 cur_val
    cur = cur_val * cur_mul  # 計算硬幣數量
    if cur > imax:  # 如果 cur 較大
        imax = cur  # 更新 imax
        idx = i  # 更新 i
print(f"{idx:d} {imax:d}")


2025年2月13日 星期四

ZeroJudge 解題筆記:e840. P7. 密碼強度測試(Passwords)

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



ZeroJudge 題目連結:e840. P7. 密碼強度測試(Passwords)

解題想法


按照題目給的規則計分就好,不過要注意連續數字的扣分方式,例如 1234,要扣的分數是 $(4-1) \times 2$。

Python 程式碼


使用時間約為 23 ms,記憶體約為 3.3 MB,通過測試。
digit = 0  # 數字數量
letter = 0  # 字母數量
cont = []  # 連續數字
s = input().strip()  # 讀取字串,用 strip 去掉最後的 \0
c1 = s[0]  # 處理 s 開頭的字元
if c1.isdigit():  # 如果 c1 是數字
    digit += 1  # digit 加 1
    cont.append([c1])  # [c1] 加到 cont
elif c1.isalpha(): letter += 1  # 如果 c1 是字母,letter 加 1
# 處理 s[1] ~ s[-1]
for i, c in enumerate(s[1:], start=1):
    if c.isdigit():  # 如果 c 是數字
        digit += 1  # digit 加 1
        if s[i-1].isdigit():  # 如果 s-1 是數字
            cont[-1].append(c)  # c 加到 cont[-1]
        else: cont.append([c])  # 如果 s-1 不是數字,[c] 加到 cont
    elif c.isalpha(): letter += 1  # 如果 c 是字母,letter 加 1
# 計算分數
score = len(s)*3 + letter*3 + digit*2  # 處理長度、字母數量、數字數量
if len(s) >= 8 and digit > 0 and letter > 0: score += 10  # 達最低要求
else: score -= 5  # 未達最低要求
if digit == 0 and letter > 0: score -= letter  # 只有英文字母
if digit > 0 and letter == 0: score -= digit  # 只有數字
for con in cont:  # 依序由 cont 讀取資料 con
    if len(con) > 1: score -= (len(con)-1)*2  # 如果 con 長度大於 1,扣分
print(score)  # 印出分數


2025年2月12日 星期三

ZeroJudge 解題筆記:e839. P6. 飲食分類 (Food)

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



ZeroJudge 題目連結:e839. P6. 飲食分類 (Food)

解題想法


這題用字典儲存各種類食物的名稱會比較方便。

Python 程式碼


使用預設的字典儲存食物名稱、種類。使用時間約為 19 ms,記憶體約為 3.3 MB,通過測試。
n = int(input())  # n 個食物
food = dict()  # 食物種類、名稱
for _ in range(n):  # 讀取 n 行資料
    f, s = input().split()  # 食物名稱 f、種類 s
    if s not in food: food[s] = [f]  # 如果 s 不在 food 之中,food[s] 設定為 [f]
    else: food[s].append(f)  # 如果 s 已經在 food 之中,food[s] 新增 f
t = input().strip()  # 要找的目標
if t not in food: print("No")  # 如果 t 不在 food 之中,印出 No
else:  # 如果 t 在 food 之中,將食物名稱排序後印出
    for f in sorted(food[t]):
        print(f)

改用 collections.defaultdict。使用時間約為 22 ms,記憶體約為 3.6 MB,通過測試。
from collections import defaultdict

n = int(input())  # n 個食物
food = defaultdict(list)  # 食物種類、名稱
for _ in range(n):  # 讀取 n 行資料
    f, s = input().split()  # 食物名稱 f、種類 s
    food[s].append(f)  # food[s] 新增 f
t = input().strip()  # 要找的目標
if t not in food: print("No")  # 如果 t 不在 food 之中,印出 No
else:  # 如果 t 在 food 之中,將食物名稱排序後印出
    for f in sorted(food[t]):
        print(f)


2025年2月11日 星期二

ZeroJudge 解題筆記:e838. P5. 炸彈超人(Bombs)

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



ZeroJudge 題目連結:e838. P5. 炸彈超人(Bombs)

解題想法


這題先將炸彈的位置儲存起來,等讀取完整個地圖資料之後再處理會比較方便。

Python 程式碼


使用時間約為 25 ms,記憶體約為 3.4 MB,通過測試。
n = int(input())  # 地圖為 n*n
bomb = []  # 炸彈位置
grid = []  # 地圖
for i in range(n):  # 讀取 n 行資料
    row = list(input().strip())  # 一行資料,轉成串列
    grid.append(row)  # row 加入 grid
    for j, ch in enumerate(row):  # 依序由 row 讀取字元 ch
        if ch == "*": bomb.append((i, j))  # ch 是炸彈,位置 (i, j) 加入 bomb
for i, j in bomb:  # 讀取炸彈位置 (i, j),將十字方向上的位置皆改成 *
    for c in range(j, -1, -1): grid[i][c] = "*"
    for c in range(j, n, 1): grid[i][c] = "*"
    for r in range(i, -1, -1): grid[r][j] = "*"
    for r in range(i, n, 1): grid[r][j] = "*"
for row in grid:  # 由 grid 依序讀取整列的資料
    print("".join(row))  # 將 row 接成字串再印出


2025年2月10日 星期一

ZeroJudge 解題筆記:e837. P4. 字母排列 (Letters)

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



ZeroJudge 題目連結:e837. P4. 字母排列 (Letters)

解題想法


這題的說明不精準,題目中說要找按照順序排列的最長字串,實際上是要找按照順序且相鄰字母的最長字串

Python 程式碼


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

for s in sys.stdin:
    s = s.strip()  # 去掉最後面的 \0
    now = s[0]  # 目前符合要求的最長字串,先放入 s[0]
    ans = ""  # 答案
    for c in s[1:]:  # 依序讀取 s[1] ~ s[-1]
        if ord(c) == ord(now[-1])+1: now += c # 如果 c 是 now[-1] 的下一個字母,將 c 接到 now 之後
        else:  # 如果 c 不是 now[-1] 的下一個字母
            if len(now) >= len(ans): ans = now  # 如果 now 的長度大於等於 ans 的長度,更新 ans
            now = c  # 更新 now
    if len(now) >= len(ans): ans = now  # 最後要再檢查一次 now 是否比 ans 長
    print(f"{len(ans):d} {ans:s}")  # 印出答案


2025年2月9日 星期日

ZeroJudge 解題筆記:e836. P3. 數字統計 (Counting)

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



ZeroJudge 題目連結:e836. P3. 數字統計 (Counting)

解題想法


這題用字典計數比較方便。

Python 程式碼


可以使用 collections 函式庫的 Counter,這是專門用來計算數量的工具,輸入一個可以迭代的物件,回傳物件中各項資料的數量。使用時間約為 45 ms,記憶體約為 3.8 MB,通過測試。
import sys
from collections import Counter

for line in sys.stdin:
    n = int(line)  # n 個數字
    rs = list(map(int, input().split()))  # 讀取一行數字
    cnt = Counter(rs)  # 計數器
    print(len(cnt))  # 印出不同的數字數量
    imax = max(cnt.values())  # 相同數字最大數量
    if imax < 2: print("NO")  # 沒有重複的數字,印出 NO
    else:  # 否則依照出現順序印出數字
        tmp = []  # 暫存用的串列
        for r in rs:  # 依序由 rs 讀取數字 r
            if cnt[r] == imax and r not in tmp:  # 如果 r 的數量最多而且不在 tmp 之中
                tmp.append(r)  # r 加入 tmp
        print(*tmp)  # 印出 tmp

由於 Counter 的 key 值會依照輸入的物件資料順序排序,上方程式第 11 到 16 行可以改為以下這行,使用時間約為 37 ms,記憶體約為 3.8 MB,通過測試。
else: print(*[key for key, val in cnt.items() if val == imax])

2025年2月8日 星期六

ZeroJudge 解題筆記:e808. 3.不再傻傻等公車 (Bus)

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



ZeroJudge 題目連結:e808. 3.不再傻傻等公車 (Bus)

解題想法


儲存公車到站時刻的串列,先將發車時刻存在開頭,之後各站牌的到站時間編號對應到串列的索引值,這樣寫比較方便。

Python 程式碼


使用時間約為 19 ms,記憶體約為 3.3 MB,通過測試。
n = int(input())  # 公車站牌數量
h, m = map(int, input().split())  # 發車時刻 h:m
time = [[h, m]] + [[0, 0] for _ in range(n)]  # 公車到站時刻
for i in range(1, n+1):  # 讀取 n 行行駛時間
    d = int(input())  # 行駛時間
    mc = time[i-1][1] + d  # 到站時刻 hc:mc
    hc = time[i-1][0]
    if mc >= 60:  # 如果 mc 大於等於 60
        hc += mc//60  # 更新 hc
        mc %= 60  # 更新 mc
    if hc >= 24: hc %= 24  # 如果 hc 大於等於 24,更新 hc
    time[i] = [hc, mc]  # 更新 time[i]
check = list(map(int, input().split()))  # 要查詢的站牌編號,最後一項是 0
for ch in check[:-1]:  # 依序從 check 讀取要查詢的站牌編號,不含最後一項
    print(f"{time[ch][0]:02d}:{time[ch][1]:02d}")


2025年2月7日 星期五

ZeroJudge 解題筆記:e807. 2.降雨量統計 (Rainfall statistics)

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



ZeroJudge 題目連結:e807. 2.降雨量統計 (Rainfall statistics)

解題想法


這題如果會用取最大值及找索引值的工具會很好寫 。

Python 程式碼


使用時間約為 26 ms,記憶體約為 3.3 MB,通過測試。
week = [0]*7  # 一週 7 天每天的累積雨量
quater = [0]*4  # 一天內 4 個時段的累積雨量
for i in range(7):  # 讀取 7 天的雨量
    M, A, N, E = map(float, input().split())
    week[i] = M + A + N + E  # 一天的累積雨量
    quater[0] += M; quater[1] += A  # 更新 4 個時段的累積雨量
    quater[2] += N; quater[3] += E
print(week.index(max(week)) + 1)  # 印出累積雨量最多的是星期幾,要加 1
name = ("morning", "afternoon", "night", "early morning")  # 時段對應的名稱
print(name[quater.index(max(quater))])  # 印出時段名稱


2025年2月6日 星期四

ZeroJudge 解題筆記:e806. 1.多項式計算 (Polynomial)

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



ZeroJudge 題目連結:e806. 1.多項式計算 (Polynomial)

解題想法


這題用 Python 的 dict、defaultdict 或 C++ 的 map、unordered_map 比較方便。

Python 程式碼


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

n = int(input())  # 第一個多項式資料有 n 對數字
imax = 0  # 最高次方
line1 = list(map(int, input().split()))  # 第一個多項式資料
poly1 = defaultdict(int)  # 用字典儲存第一個多項式的次方、係數
for i in range(0, 2*n, 2):  # 依序由 line1 讀取資料,每次跳 2 格
    poly1[line1[i]] = line1[i+1]
    imax = max(imax, line1[i])
m = int(input())  # 第二個多項式資料有 m 對數字
line2 = list(map(int, input().split()))  # 第二個多項式資料
poly2 = defaultdict(int)  # 用字典儲存第一個多項式的次方、係數
for i in range(0, 2*m, 2):  # 依序由 line2 讀取資料,每次跳 2 格
    poly2[line2[i]] = line2[i+1]
    imax = max(imax, line2[i])
ans = [0]*(imax+1)  # 儲存答案用的串列,依序為 0 ~ imax 次項的係數
for i in range(imax+1):  # 依序讀取兩個多項式 0 ~ imax 次項的係數
    ans[i] = poly1[i] + poly2[i]
if all(ans[i] == 0 for i in range(imax+1)):  # 如果 ans 每項都是 0
    print("NULL!")  # 印出 NULL!
else:  # 否則依序印出次方及係數,若係數為 0 跳過此項
    for i in range(imax, -1, -1):  # 依序印出 imax 次方項 ~ 常數項
        if ans[i] != 0:
            print(f"{i:d}:{ans[i]:d}")

2025年2月5日 星期三

ZeroJudge 解題筆記:e801. p8. 排課表

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



ZeroJudge 題目連結:e801. p8. 排課表

解題想法


這題考貪心法,先將課程依照結束時間由小到大排序,再依序讀取課程是星期幾 w、開始時間 s、結束時間 e,如果星期 w 還沒有選課則加入 (s, e);如果已經選課而且 s 大於等於 chose[w] 最後一項結束時間,可以選課。

Python 程式碼


使用時間約為 0.4 s,記憶體約為 15.3 MB,通過測試。
import sys

for line in sys.stdin:
    N = int(line)  # N 種課程
    course = [list(map(int, input().split())) for _ in range(N)]  # 讀取 N 行
    course.sort(key = lambda x : x[2])  # 依照結束時間由小到大排序
    chose = [[] for _ in range(6)]  # 一週內每天可以的課程開始、結束時間
    for w, s, e in course:  # 依序由 course 讀取課程是星期幾 w、開始時間 s、結束時間 e
        if not chose[w]:  # 如果星期 w 還沒有選課
            chose[w] = [(s, e)]  # 加入 (s, e)
        elif s >= chose[w][-1][1]:  # 如果 s 大於等於 chose[w] 最後一項結束時間,可以選課
            chose[w].append((s, e))  # 加入 (s, e)
    print(sum([len(ch) for ch in chose]))  # 將 chose 所有的項目數量加起來


2025年2月4日 星期二

ZeroJudge 解題筆記:e800. p7. 影片推薦

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



ZeroJudge 題目連結:e800. p7. 影片推薦

解題想法


這題考排序,如果用 Python 解題需要用 functools.cmp_to_key 自訂比較式,如果用 C++ 可以在 sort 裡面用 lambda function 寫比較式,也可以將比較式放在外面。

Python 程式碼


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

def mycmp(a, b):  # 自訂比較用的函式
    pa = a[2]*a[4]*a[5]/a[3]  # a 的優先推薦指數
    pb = b[2]*b[4]*b[5]/b[3]  # b 的優先推薦指數
    if pa > pb: return -1  # 如果 pa 大於 pb,a 往前放
    elif pa < pb: return 1  # 如果 pa 小於 pb,a 往後放
    else:  # 如果 pa 等於 pb
        if a[0] < b[0]: return 1  # 如果 a 的編號較小,a 往前放
        elif a[0] > b[0]: return -1  # 如果 a 的編號較大,a 往後放
        else: return 0  # 如果 a、b 的編號相等,不換順序

N = int(input())  # 影片個數
# 影片資料,內容為 [編號 i, 名稱 S, 觀看人數 P, 影片長度 L, 平均觀看時間 W, 相關係數 R]
data = []
for i in range(1, N+1):  # 讀取 N 行資料
    d = input().split()  # 拆開成串列
    data.append([i, d[0], int(d[1]), int(d[2]), int(d[3]), int(d[4])])  # 加入 data
data.sort(key = cmp_to_key(mycmp))  # 依照 mycmp 排序
for d in data: print(d[1])  # 印出排序後的影片名稱


2025年2月3日 星期一

ZeroJudge 解題筆記:e799. p6. 資工系的浪漫

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



ZeroJudge 題目連結:e799. p6. 資工系的浪漫

解題想法


這題用 Python 解題很方便,因為有內建的函式可以將整數轉換成 2 進位制的字串,如果用 C++ 就要自己寫轉換用的函式。

Python 程式碼


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

for line in sys.stdin:
    N, M = map(int, line.split())  # 圖形的高 N、寬 M
    C = input().strip()  # 字元 C,要用 strip() 刪除最後的 \n
    for _ in range(N):  # 讀取 N 行數字
        s = bin(int(input()))[2:]  # 讀取數字,用 bin 轉成 2 進位制的字串,刪除開頭的 0b
        if len(s) < M: s = "0"*(M-len(s)) +s  # 若 s 長度小於 M,在前面補 0
        for i, ch in enumerate(s):  # 依序由 s 讀取字元 ch,索引值 i
            if ch == "1": print(C, end="\n" if i == M-1 else " ")  # 如果 ch 是 1 印出符號 C
            else: print(".", end="\n" if i == M-1 else " ")  # 否則印出 .


2025年2月2日 星期日

ZeroJudge 解題筆記:e798. p5. 卷積神經網路

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



ZeroJudge 題目連結:e798. p5. 卷積神經網路

解題想法


可以讀取完整個矩陣的資料再處理最大池化,也可以每讀 2 列矩陣資料就輸出一次最大池化的結果,效率差不多。

Python 程式碼


使用時間約為 18 ms,記憶體約為 3.3 MB,通過測試。
n = int(input())  # 矩陣大小 n*n
mat = [list(map(int, input().split())) for _ in range(n)]  # 讀取矩陣資料
pool = [[0]*(n//2) for _ in range(n//2)]  # 儲存最大池化的結果
for r in range(0, n, 2):  # 依序掃過第 0 ~ n-1 列,每次跳 2 列
    for c in range(0, n, 2):  # 依序掃過第 0 ~ n-1 欄,每次跳 2 欄
        pool[r//2][c//2] = max(mat[r][c], mat[r][c+1], mat[r+1][c], mat[r+1][c+1])  # 取 4 格中的最大值
for row in pool: print(*row)  # 依序印出 pool 每列的資料

每讀取 2 列就輸出 1 次,使用時間約為 19 ms,記憶體約為 3.3 MB,通過測試。
n = int(input())  # 矩陣大小 n*n
for r in range(0, n, 2):  # 依序掃過第 0 ~ n-1 列,每次跳 2 列
    row1 = list(map(int, input().split()))  # 讀取 2 列
    row2 = list(map(int, input().split()))
    pool = [0]*(n//2)  # 儲存最大池化結果的串列
    for c in range(0, n, 2):  # 依序掃過第 0 ~ n-1 欄,每次跳 2 欄
        pool[c//2] = max(row1[c], row1[c+1], row2[c], row2[c+1])  # 取 4 格中的最大值
    print(*pool)  # 印出 pool 的資料


2025年2月1日 星期六

ZeroJudge 解題筆記:e797. p4. 數位邏輯運算

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



ZeroJudge 題目連結:e797. p4. 數位邏輯運算

解題想法


要小心,每組測資有多筆測試資料。

Python 程式碼


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

for line in sys.stdin:  # 繼續執行直到沒有資料為止
    N, T = map(int, line.split())  # N 個訊號,T 個時間點
    data = [list(map(int, input().split())) for _ in range(N)]  # 訊號資料
    a, b, c = [0]*T, [0]*T, [0]*T  # AND, OR, XOR 的結果
    for i in range(T):  # 依序檢查 T 個時間點
        one = 0  # 訊號 1 的數量
        for j in range(N):  # 依序檢查 N 個訊號
            if data[j][i] == 1: one += 1  # 訊號 1,one 加 1
        if one == N: a[i] = 1  # 訊號是 N 個 1,a[i] = 1
        if one > 0: b[i] = 1  # 訊號至少有 1 個 1,b[i] = 1
        if one%2 == 1: c[i] = 1  # 訊號是奇數個 1,c[i] = 1
    print("AND:", *a)
    print(" OR:", *b)
    print("XOR:", *c)