POJ 1013--Counterfeit Dollar(假币问题)(枚举,假设)
程序员文章站
2022-05-13 17:06:49
...
POJ 1013–Counterfeit Dollar(假币问题)(枚举,假设)
描述
赛利有12枚银币。其中有11枚真币和1枚假币。假币看起来和真币没有区别,但是重量不同。但赛利不知道假币比真币轻还是重。于是他向朋友借了一架天平。朋友希望赛利称三次就能找出假币并且确定假币是轻是重。例如:如果赛利用天平称两枚硬币,发现天平平衡,说明两枚都是真的。如果赛利用一枚真币与另一枚银币比较,发现它比真币轻或重,说明它是假币。经过精心安排每次的称量,赛利保证在称三次后确定假币。
输入
第一行有一个数字n,表示有n组测试用例。
对于每组测试用例:
输入有三行,每行表示一次称量的结果。赛利事先将银币标号为A-L。每次称量的结果用三个以空格隔开的字符串表示:天平左边放置的硬币 天平右边放置的硬币 平衡状态。其中平衡状态用up’’,down”, 或 “even”表示, 分别为右端高、右端低和平衡。天平左右的硬币数总是相等的。
输出
输出哪一个标号的银币是假币,并说明它比真币轻还是重(heavy or light)。
样例输入
1
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
样例输出
K is the counterfeit coin and it is light.
解题思路:
枚举某一硬币的类型,先定位假币(重量大
1
或 重量小-1
),再将其还原为真币重量0
。需要注意以下几点:
一、一定有假币存在且数量为1.
二、天平两边可以放最多6个。
三、枚举过程中不满足即可跳出,如果三个都满足即可返回1
,当其为假币时,满足输入的三个条件,就确定假设为真,即当前第i(字母表示)
个为假币.
代码实现:
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
char a[3][10],b[3][10],c[3][10];//记录左天平a,右天平b,状态c 三种条件情况
int S[15];//记录当前硬币是第几个
int G()//判断假设是否满足三个条件
{
int left,right;
for(int i=0;i<3;i++)
{
left=0;
right=0;
for(int j=0;j<6&&a[i][j]!=0&&b[i][j]!=0;j++)
{
left+=S[a[i][j]-'A'];
right+=S[b[i][j]-'A'];
}
if(left>right&&c[i][0]!='u')return 0;
if(left<right&&c[i][0]!='d')return 0;
if(left==right&&c[i][0]!='e')return 0;
}
return 1;
}
int main()
{
int x;
scanf("%d",&x);
getchar();
while(x--)
{
for(int i=0;i<3;i++)
{
scanf("%s %s %s",a[i],b[i],c[i]);
}
memset(S,0,sizeof(S));//设硬币重量默认都为0
for(int i=0;i<12;i++)
{
S[i]=1;//先假设当前i这个硬币是重的假币记为1
G();
if(G()==1){printf("%c is the counterfeit coin and it is heavy.\n",'A'+i);break;}
/*如果3条件全部满足符合则输出当前正确的假设*/
S[i]=-1;//先假设当前i这个硬币是轻的假币记为-1
G();
if(G()==1){printf("%c is the counterfeit coin and it is light.\n",'A'+i);break;}
/*如果3条件全部满足符合则输出当前正确的假设*/
S[i]=0;//将当前硬币记录为真币,进行后续运算
}
}
}
下一篇: jquery图片切换插件_jquery