假币问题
有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;
}