程式設計菜鳥到大佬之路:演算法基礎(三)
阿新 • • 發佈:2019-01-05
第三天學習精要
列舉
稱硬幣
- 例題3:POJ1013 稱硬幣
- 題目描述
- 有12枚硬幣。其中有11枚真幣和1枚假幣。
- 假幣和真幣重量不同,但不知道假幣比真幣輕還是重。
- 現在,用一架天平稱了這些幣三次,告訴你稱的結果,請你找出假幣並且確定假幣是輕是重(資料保證一定能找出來)。
- 輸入
- 第一行是測試資料組數。
- 每組資料有三行,每行表示一次稱量的結果。
- 銀幣標號為A-L。
- 每次稱量的結果用三個以空格隔開的字串表示:天平左邊放置的硬幣,天平右邊放置的硬幣,平衡狀態。
- 其中平衡狀態用 up, down, 或 even 表示,分別為右端高、右端低和平衡。
- 天平左右的硬幣數總是相等的。
- 輸出
- 輸出哪一個標號的銀幣是假幣,並說明它比真幣輕還是重。
- 輸入樣例
- 1
- ABCD EFGH even
- ABCI EFJK up
- ABIJ EFGH even
- 輸出樣例
- K is the counterfeit coin and it is light。
- 解題思路
- 對於每一枚硬幣先假設它是輕的,看這樣是否符合稱量結果。
- 如果符合,問題即解決。
- 如果不符合,就假設它是重的,看是否符合稱量結果。
- 把所有硬幣都試一遍,一定能找到特殊硬幣。
# include <iostream> # include <cstring> using namespace std; char Left[3][7]; // 天平左邊硬幣,最多稱三次,左邊最多放六枚硬幣,例如Left[0][4]代表第一次稱量時左邊有四枚硬幣 char Right[3][7]; // 天平右邊硬幣,最多稱三次,右邊最多放六枚硬幣 char Result[3][7]; // 結果,可能是even,up,down bool IsFake(char c, bool light); // light為真表示假設假幣為輕,否則表示假設假幣為重 int main(){ int t; // t代表測試資料的組數 cin >> t; while (t--){ // 對每一組資料把三次測量結果讀進來 for (int i = 0; i < 3; ++i){ cin >> Left[i] >> Right[i] >> Result[i]; // 讀入的是三個字串,分別放入三個陣列 } for (char c = 'A'; c <= 'L'; c++){ if (IsFake(c, true)){ // 列舉一個個找出假幣c,認為c是輕的假幣 cout << c << " is the counterfeit coin and it is light.\n"; break; }else if (IsFake(c, false)){ // 列舉一個個找出假幣c,認為c是重的假幣 cout << c << " is the counterfeit coin and it is heavy.\n"; break; } } } return 0; } bool IsFake(char c, bool light){ // c表示假設哪一枚是假幣,light為真表示假設假幣為輕,否則表示假設假幣為重 for (int i = 0; i < 3; ++i){ // 分析三次的稱量結果,三次都不矛盾,假設為真 char *pLeft, *pRight; // 指向天平兩邊的字串 if (light){ pLeft = Left[i]; // Left[i]是指第i次稱量時天平左邊所放的字串 pRight = Right[i]; // Right[i]是指第i次稱量時天平右邊所放的字串 }else{ // 如果假設假幣是重的,則把稱量結果左右對換 pLeft = Right[i]; pRight = Left[i]; } switch (Result[i][0]){ // 天平右邊的情況,此時認為c是輕的假幣,看看第i次的稱量結果是否和假設矛盾 case 'u': // 天平右邊高於左邊 if (strchr(pRight, c) == NULL) // C應該出現在pRight所指向的字串,但是假幣c沒有出現在右邊 return false; // 假設c是輕的假幣是錯誤的 break; case 'e': // 天平兩邊一樣高 if (strchr(pLeft, c) || strchr(pRight, c)) // c不應該出現在左邊或者右邊的字串,如果c出現了 return false; // 假設c是輕的假幣是錯誤的 break; case 'd': // 天平右邊低於左邊 if (strchr(pLeft, c) == NULL) // C應該出現在pLeft所指向的字串,但是假幣c沒有出現在左邊 return false; // 假設c是輕的假幣是錯誤的 break; } } return true; }
- 題目描述