题目描述:12个金币中有一个是假币,假币的大小颜色都和真的一样,只有重量不一样,但是有可能比真的轻,也有可能重,现在要通过称重找出那个假的。
输入格式:第一行一个整数n,表示有n组数据,每组数组有3行输入,每行由被2个空格隔开的三个字符串组成,表示一次称重的结果,前字符串由A-L的大写英文字母组成,分别表示天平左边和右边分别放的金币编号。第三个字符串有三种情况”even”,”up”,”down”.分别表示平衡,左边轻,右边轻。
输出格式:每组数据输出一行,表示哪个金币是假币,并输出是比真币重还是轻。例如:K is the counterfeit coin and it is light.
数据保证:并没有任何保证,如果只有12个币不算的话、
解题思路:
- 首先明确的是,如果是even,则此次称重的所有金币(左右两边的)都是真的。
- 其次,又在重的一边出现过又在轻的一边出现过的金币是真的。(即在两次称重中处于不同的状态的金币是真的)
- 最后,在重的一边或轻的一边次数最多的是假币(这个我也不知道为什么,我按照前面两点写出来的算法有错误,然后对着数据看了一下,假币up的次数多,所以。。。)
PS:最近两道题目的题意都是我自己看懂的。没看翻译,只是想好好练习我的英语,似乎效果还可以,要坚持下去!
#include <cstdio>
#define abs(a) ({ (a)>0?(a):-(a); })
int main(int argc, char const *argv[])
{
int n;
char s1[3][100], s2[3][100], s3[3][100];
for(scanf("%d", &n); n--;){
int u[20]={0}, d[20]={0};
bool e[20]={false};
for(int i=0; i<3; ++i){
scanf("%s%s%s", s1[i], s2[i], s3[i]);
for(int j=0; s1[i][j] && s2[i][j]; ++j){
switch(s3[i][0]){
case 'e':
e[s1[i][j]-'A']=true;
e[s2[i][j]-'A']=true;
break;
case 'u':
u[s1[i][j]-'A']++;
d[s2[i][j]-'A']++;
break;
case 'd':
d[s1[i][j]-'A']++;
u[s2[i][j]-'A']++;
break;
default:
break;
}
}
}
int max=-1, ans=-1;
for(int i=0; i<12; ++i){
if(u[i]&&d[i]) { e[i]=true; }
if(e[i]) { continue; }
int tmp=abs(u[i]-d[i]);
if(tmp>max){ max=tmp; ans=i; }
}
printf("%c is the counterfeit coin and it is %s.\n", 'A'+ans, u[ans]<d[ans]?"light":"heavy");
}
return 0;
}