12 枚硬幣 A-L,其中 1 枚偽幣(輕或重)。3 次天平稱重,每次給出左右盤硬幣與結果(up/down/even)。唯一確定偽幣及輕重。
-1,右盤 +1,未參與 0// 實際結果編碼:even=0, up=1, down=-1
// 硬幣 c 假設為輕:預期結果 = -contribution[c][i]
// 硬幣 c 假設為重:預期結果 = +contribution[c][i]
for (int c = 0; c < 12; ++c) {
// 假設輕
bool ok_light = true;
for (int i = 0; i < 3; ++i)
if (actual[i] != -contrib[c][i]) { ok_light = false; break; }
if (ok_light) { answer = c, "light"; break; }
// 假設重
bool ok_heavy = true;
for (int i = 0; i < 3; ++i)
if (actual[i] != contrib[c][i]) { ok_heavy = false; break; }
if (ok_heavy) { answer = c, "heavy"; break; }
}
score[12] = {0}score = 10(標記為真幣,不再修改)++,右盤 ----,右盤 ++|score| 最大且 ≠10 的硬幣為偽幣score > 0 → heavy, score < 0 → light#includeusing namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int score[12] = {0}; for (int w = 0; w < 3; ++w) { string left, right, result; cin >> left >> right >> result; if (result == "even") { for (char c : left) score[c-'A'] = 10; for (char c : right) score[c-'A'] = 10; } else if (result == "up") { // left down / right up for (char c : left) if (score[c-'A'] != 10) score[c-'A']++; for (char c : right) if (score[c-'A'] != 10) score[c-'A']--; } else { // down for (char c : left) if (score[c-'A'] != 10) score[c-'A']--; for (char c : right) if (score[c-'A'] != 10) score[c-'A']++; } } int idx = 0, max_diff = 0; for (int i = 0; i < 12; ++i) { if (score[i] != 10 && abs(score[i]) > max_diff) { max_diff = abs(score[i]); idx = i; } } cout << char('A'+idx) << " is the counterfeit coin and it is " << (score[idx] > 0 ? "heavy" : "light") << ".\n"; } return 0; }
| 維度 | 假設驗證法 | 差值累積法 |
|---|---|---|
| 思路來源 | 邏輯推演 | 啟發式歸納 |
| 代碼長度 | ~40 行 | ~30 行 |
| 易理解性 | 高(物理意義清晰) | 中(需驗證為何有效) |
| 擴展性 | 強(可處理更多稱重、硬幣) | 弱(依賴題目特定約束) |
| 調試難度 | 低 | 中 |
c-'A' 索引POJ 1017 是邏輯推理與編程實現結合的經典題。假設驗證法邏輯嚴密、擴展性強,適合面試講解;差值累積法代碼極簡、工程效率高,適合競賽現場。掌握「Even 全真、偽幣必傾斜、方向一致性」三大核心規則,即可靈活構造解法。本題體現了「用數據結構(哈希/數組)模擬邏輯規則」的競賽編程核心思想。