假幣問題
有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]; //左邊天平
char Right[3][7]; //右邊天平
char result[3][7]; //結果
bool isfake(char c,bool light); //light爲真表示假設假幣爲輕
int main()
{
int 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)){
cout<<c<<"is the counterfeit coin and it is light.\n";
break;
}
else if(isfake(c,false)){
cout<<c<<"is the counterfeit coin and it is light.\n";
break;
}
}
}
return 0;
}
bool isfake(char c,bool light){
for(int i=0;i<3;i++){
char *pleft,*pright;
//因爲天平反映的是右邊的情況
//當假設假幣輕時,若假幣在右邊則右邊up,在左邊則右邊down
//當假設假幣重時,若假幣在右邊則右邊down,在左邊則右邊up
//當假設假幣重時,用指針調換天平的兩側,使得若假幣在右邊則右邊up
if(light){
pleft=Left[i];
pright=Right[i];
}
else{
pleft=Right[i];
pright=Left[i];
}
switch(result[i][0]){ //天平右邊的情況
case 'u': //右邊輕
if(strchr(pright,c)==NULL)
return false;
break;
case 'e':
if(strchr(pleft,c)||strchr(pright,c))
return false;
break;
case 'd': //右邊重
if(strchr(pleft,c)==NULL)
return false;
break;
}
}
return true;
}