熱門文章

2026年4月19日 星期日

ZeroJudge 解題筆記:d132. 00340 - Master-Mind Hints

作者:王一哲
日期:2026年4月19日


ZeroJudge 題目連結:d132. 00340 - Master-Mind Hints

解題想法


先讀取答案 $ans$,計算 $0$ 到 $9$ 的數量存入串列 $cntAns$。接下來讀取猜測的數字 $guess$,如果數字都是 $0$ 就中止迴圈;將 $cntAns$ 複製一份到串列 $cnt$,依序檢查 $ans, guess$ 的每個位數,找出位置、數字皆相等的數字並更新 $A$ 的值,如果數字對但位置錯則存入串列 $remain$,最後再從 $remain$ 的資料計算 $B$ 的值。

Python 程式碼


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

num = 0  # 計算第幾次遊戲用的計數器
for line in sys.stdin:  # 繼續執行直到沒有讀到字串為止
    if line == "0\n": break  # 如果讀到 0\n 結束 for 迴圈
    n = int(line.strip())  # 讀取答案的位數
    num += 1  # num 加 1
    print(f"Game {num:d}:")  # 印出遊戲次數
    ans = list(map(int, input().split()))  # 讀取答案
    cntAns = [0]*10  # 因為題目限制只有 1 ~ 9 的數字,用長度為 10 的串列計數即可
    for a in ans: cntAns[a] += 1  # 在外面跑一次就好
    for line2 in sys.stdin:  # 繼續讀取字串
        guess = list(map(int, line2.split()))  # 讀取猜測的數字
        if all(g == 0 for g in guess): break  # 如果猜的數字都是 0,結束這次的遊戲
        cnt = cntAns.copy()  # 等一下會被修改掉,複製一份到 cnt
        remain = []  # 用來記錄沒有對到正確位置的數字
        A, B = 0, 0  # 值及位置都正確數字數量,只有值正確但位置錯的數字數量
        for a, g in zip(ans, guess):  # 依序由 ans 及 guess 讀取資料 a, g
            if a == g:  # 如果 a 等於 g,值及位置都正確
                A += 1  # A 加 1
                cnt[a] -= 1  # a 對應的數量減 1
            elif cnt[g] > 0: remain.append(g)  # 如果值對但位置錯,將 g 加入 remain
        for r in remain:  # 依序由 remain 讀取資料 r
            if cnt[r] > 0:  # 如果 r 在 cnt 之中的數量大於 0 
                cnt[r] -= 1  # r 在 cnt 之中的數量減 1
                B += 1  # B 加 1
        print(f"    ({A:d},{B:d})")  # 印出答案


C++ 程式碼


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

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int num = 0;  // 計算第幾次遊戲用的計數器
    string line;  // 暫存讀取資料用的字串
    while(cin >> line) {  // 繼續執行直到沒有讀到字串為止
        if (line == "0") break;  // 如果讀到 0 結束 while 迴圈
        int n = stoi(line);  // 讀取答案的位數
        num++;  // num 加 1
        cout << "Game " << num << ":\n";  // 印出遊戲次數
        vector<int> ans (n);  // 讀取答案
        for(int i=0; i<n; i++) cin >> ans[i];
        vector<int> cntAns (10, 0);  // 因為題目限制只有 1 ~ 9 的數字,用長度為 10 的串列計數即可
        for(int a : ans) cntAns[a]++;  // 在外面跑一次就好
        while(true) {  // 繼續讀取字串
            vector<int> cnt (cntAns.begin(), cntAns.end());  // 等一下會被修改掉,複製一份到 cnt
            bool flag = true;  // 所有猜測的數字都是 0
            vector<int> guess (n);  // 讀取猜測的數字
            for(int i=0; i<n; i++) {
                int g; cin >> g;
                if (g != 0) flag = false;  // 只要其中一個猜測的數字不是 0,flag 設定為 false
                guess[i] = g;
            }
            if (flag) break;  // 如果所有猜測的數字都是 0,結束這次的遊戲
            vector<int> remain;  // 用來記錄沒有對到正確位置的數字
            int A = 0, B = 0;  // 值及位置都正確數字數量,只有值正確但位置錯的數字數量
            for(int i=0; i<n; i++) {  // 依序由 ans 及 guess 讀取資料 a, g
                int a = ans[i], g = guess[i];
                if (a == g) {  // 如果 a 等於 g,值及位置都正確
                    A++;  // A 加 1
                    cnt[a]--;  // a 對應的數量減 1
                } else if (cnt[g] > 0) {  // 如果值對但位置錯,將 g 加入 remain
                    remain.push_back(g);
                }
            }
            for(auto r : remain) {  // 依序由 remain 讀取資料 r
                if (cnt[r] > 0) {  // 如果 r 在 cnt 之中的數量大於 0 
                    cnt[r]--;  // r 在 cnt 之中的數量減 1
                    B++;  // B 加 1
                }
            }
            cout << "    (" << A << "," << B << ")\n";  // 印出答案
        }
    }
    return 0;
}


沒有留言:

張貼留言