【题意简述】:赛利有 12 枚银币。其中有 11 枚真币和 1 枚假币。假币看起来和真币没有区别,但是重量不同。但赛利不知道假币比真币轻还是重。于是他向朋友借了一架天平。朋友希望赛利称三次就能找出假币并且确定假币是轻是重。例如:如果赛利用天平称两枚硬币,发现天平平衡,说明两枚都是真的。如果赛利用一枚真币与另一枚银币比较,发现它比真币轻或重,说明它是假币。经过精心安排每次的称量,赛利保证在称三次后确定假币。
【思路】:此题中赛利已经设计了正确的称量方案,保证从三组称量数据中能得到唯一的答案。答案可以用两个变量表示:x假币的标号、w假币是比真币轻还是比真币重。x 共有 12 种猜测;w 有 2 种猜测。根据赛利设计的称量方案,(x,w )的 24 种猜测中,只有唯一的猜测与三组称量数据都不矛盾。因此,如果猜测(x,w )满足下列条件,这个猜测就是要找的答案:
在称量结果为"even'' 的天平两边,没有出现 x ;
如果 w 表示假币比真币轻,则在称量结果为"up'' 的天平右边一定出现 x、在称量结果为"down'' 的天平左边一定出现 x
如果 w 表示假币比真币重,则在称量结果为"up'' 的天平左边一定出现 x、在称量结果为"down'' 的天平右边一定出现 x
具体实现时,要注意两点:
1) 选择合适的算法
对于每一枚硬币 x 逐个试探:
x 比真币轻的猜测是否成立?猜测成立则进行输出。
x 比真币重的猜测是否成立?猜测成立则进行输出。
/* 132K 0Ms */
#include<iostream>
#include<cstring>
using namespace std;
char lef[3][7],righ[3][7],result[3][5];
bool isHeavy(char);
bool isLight(char);
int main()
{
int n;
char c;
scanf("%d",&n);
while(n--)
{
for(int i =0 ;i<3;i++)
scanf("%s%s%s",lef[i],righ[i],result[i]);
for(c = 'A';c<='L';c++)
{
if(isLight(c))
{
printf("%c is the counterfeit coin and it is light.\n", c);
break;
}
if(isHeavy(c))
{
printf("%c is the counterfeit coin and it is heavy.\n", c);
break;
}
}
}
return 0;
}
bool isLight(char x)
{
int i;
for(i = 0;i<3;i++)
switch(result[i][0])
{
case 'u':if(strchr(righ[i],x) == NULL) return false;
break;
case 'e':if(strchr(righ[i],x) != NULL||strchr(lef[i],x) != NULL) return false;
break;
case 'd':if(strchr(lef[i],x) == NULL) return false;
}
return true;
}
bool isHeavy(char x)
{
int i;
for(i = 0;i<3;i++)
switch(result[i][0])
{
case 'u':if( strchr(lef[i], x) == NULL) return false;
break;
case 'e':if(strchr(righ[i],x) != NULL||strchr(lef[i], x) != NULL) return false;
break;
case 'd':if(strchr(righ[i], x) == NULL) return false;
break;
}
return true;
}