Counterfeit Dollar
Happily, Sally has a friend who loans her a very accurate balance scale. The friend will permit Sally three weighings to find the counterfeit coin. For instance, if Sally weighs two coins against each other and the scales balance then she knows these two coins are true. Now if Sally weighs one of the true coins against a third coin and the scales do not balance then Sally knows the third coin is counterfeit and she can tell whether it is light or heavy depending on whether the balance on which it is placed goes up or down, respectively.
By choosing her weighings carefully, Sally is able to ensure that she will find the counterfeit coin with exactly three weighings.
1 ABCD EFGH even ABCI EFJK up ABIJ EFGH even
K is the counterfeit coin and it is light.
这是今天我们新队员的练习题的C题。因为,无人AC所以我在此做下题解。(这个题我自己也是碰到不只一次了,幸好在暑假时看过一个某大神的题解琢磨了整整一天并且AC了,现在还大概记得思路。不得不说当我自己准备开始做这个题时我也后悔了出这个题。)
首先先说题意:一共有12个硬币,但是,其中必然有一个是不合格的硬币。这个硬币可能比正常的硬币更重,也可能比正常的硬币更轻。现在把所有的硬币依次标记成‘ A ’~‘ K ’,要求你在三次称量后指出不合格的硬币是哪个?而且是更轻还是更重。在这个题中有几个保证:1、在输入的数据中必然有一个不合格的硬币。2、在输入的数据中有且只有一个答案。(题目中的这两个保证很重要。)
然后是思路:
既然题中要我们得出不合格的硬币是哪个那么我就把每个不同的硬币根据称量结果的不同进行标记。
1. 如果一边的硬币比较轻就把它们标记成-1。如果更重就标记成2。(所有的硬币初始化是初始成0。).
2.如果,有某个硬币之前的称量中是偏轻。(也就是-1)然后此次的称量中偏重,则这个硬币必为合格硬币。(具体原因和情况就不做阐述,反正也是如此。)
3.因为题目中已经说明对于每组输入的数据中只有一个不合格硬币,而且有且只有一个正确答案。所以,我们不妨就对于那些“一错再错”的硬币进行“罪加一等”。(对于像第二个条件中的那些“知错就改”的硬币就直接判它“无罪”。)因为,如果那个不合格的硬币是偏轻(偏重),只要它所在的那边也必然是偏轻(偏重)。而对于那些正常的硬币则不是,它们只有当和不合格的硬币在一起时它才会被怀疑是偏轻(偏重),而在不合格的硬币的另一边时则被怀疑成是偏重(偏轻)。
也许这个解释不太好理解,但是,慢慢消化,慢慢想想就会想通的。因为在题目中已经说明了,对于每一组输入的数据必然有且只有一个唯一的答案。
接下来就是上代码了:(如果你已经写好了代码,建议你先拉到最下面查看那些容易出错的数据。)
#include<stdio.h>
#include<string.h>
int coin[15]; //使用coin数组来记录每个硬币是偏重还是偏轻,同时还包括程度。
char left[12];
char right[12];
/*下面这个就是当天平不平衡时的需要使用的判断函数。其中第一个传入的参数是较轻一方的硬币,
第二个参数是较重一方的硬币。第三个是两个字符串的长度。(你也可以理解成此方硬币的数量)*/
void judge(char light[],char heavy[],int len){ //当天平不平衡时进行判断的函数。
for(int j=0; j<len; j++){
if(coin[light[j]-'A']==0) //对于较轻的硬币如果它之前还是0那这次就是它犯罪的开始
coin[light[j]-'A']=-1;
else if(coin[light[j]-'A']>1) //如果这个硬币它之前有过被怀疑是偏重现在又是偏轻。
coin[light[j]-'A']=1; //则这个硬币必为合格硬币。(思路第二条。)
else if(coin[light[j]-'A']<0) //如果这个硬币之前还是偏轻现在还是偏轻。
coin[light[j]-'A']-=1;//那就对它罪加一等。
if(coin[heavy[j]-'A']==0) //对于较重的硬币如果它之前还是0那这次就是它犯罪的开始。
coin[heavy[j]-'A']=2;
else if(coin[heavy[j]-'A']<0) //如果这个硬币它之前还是被怀疑是偏轻现在有事偏重
coin[heavy[j]-'A']=1; //则这个硬币必为合格硬币。
else if(coin[heavy[j]-'A']>1) //如果这个硬币之前还是偏重现在还是偏重。
coin[heavy[j]-'A']+=1;//那就对它罪加一等。
}
}
int main(){
int n;
//freopen("数据输入.in","r",stdin); //这是在检测数据进行调试时常用的一个语句。
while(scanf("%d",&n)!=EOF) {
int j;
while(n--){ //一共有n组数据每组输入称量三次。
memset(coin,0,sizeof(coin)); //对每个硬币的记录进行初始化,初始化为0。
for(j=0;j<3;j++){
char state[5]; //在每次的输入中输入左右两边硬币的状态,up,even或者down
scanf("%s",left); //对天平左边的硬币进行输入。
scanf("%s",right); //对天平右边的硬币进行输入
scanf("%s",state); //输入天平此时的状态。
int l=strlen(left);
if(state[0]=='e') {//因为三个状态的首字母都不同,所以,我们只需通过输入状态的首字母即可
for(int k=0; k<l; k++) { //当首字母是'e'时对应输入的状态就是even。
coin[left[k]-'A']=1; //在此时就直接确定两边的硬币都是合格的标记成'1'。
coin[right[k]-'A']=1;
}
}
if(state[0]=='u') //当状态的首字母是'u'时对应的就是up。也就是左重又轻。
judge(right,left,l);//此时向判断judge函数中传入参数。右边的硬币
//作为重的一组传入,左边的则作为轻的一方传入。
if(state[0]=='d') //当状态的首字母是'd'时对应的就是down,也就是左轻又重。
judge(left,right,l);//此时向判断judge函数中传入参数.左边的硬币
//作为重的一组传入,右边的则作为轻的一组传入。
}
int max=0; //用max来记下那个“罪刑”最重的硬币。
int w; //用w来记下“罪刑”最重的硬币的位置。
for(j=0;j<12;j++) { //在判断“罪刑”时涉及两种情况一种是偏轻,另一种是偏重。
//printf("%d/",coin[j]); //在这里加上一个备注输出的是每个硬币中最后的“罪刑”。(有助于调试程序。)
if(coin[j]<0&&max<-coin[j]) { //当硬币是偏轻时因为他是以-1为起点,所以,离0越远则“罪刑”越重。
max=-coin[j];
w=j;
}
if(coin[j]>1&&max<coin[j]-1) {//当硬币是偏重时因为他是以2为起点,所以,离1越远则“罪刑“越重。
max=coin[j]-1;
w=j;
}
}
printf("%c is the counterfeit coin and it is ",w+'A');//把记录下的位置转化成字符输出。
if(coin[w]<0) //通过判断不合格硬币中的值来断定此硬币是偏重还是偏轻。
printf("light.\n");
else
printf("heavy.\n");
}
}
//fclose(stdin);
}
12
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
AGHL BDEC even
JKI ADE up
J K even
ABCDEF GHIJKL up
ABC DEF even
I J down
ABCDEF GHIJKL up
ABHLEF GDIJKC down
CD HA even
A B up
B A down
A C even
A B up
B C even
DEFG HIJL even
ABC DEJ down
ACH IEF down
AHK IDJ down
ABCD EFGH even
AB IJ even
A L down
EFA BGH down
EFC GHD even
BA EF down
A B up
A C up
L K even
ACEGIK BDFHJL up
ACEGIL BDFHJK down
ACEGLK BDFHJI down
ACEGIK BDFHJL up
ACEGIL BDFHJK down
ACEGLK BDFHJI up
对于上面每一组数据对应的输出是:
K is the counterfeit coin and it is light.
I is the counterfeit coin and it is heavy.
I is the counterfeit coin and it is light.
L is the counterfeit coin and it is light.
B is the counterfeit coin and it is light.
A is the counterfeit coin and it is heavy.
A is the counterfeit coin and it is light.
L is the counterfeit coin and it is heavy.
A is the counterfeit coin and it is light.
A is the counterfeit coin and it is heavy.
L is the counterfeit coin and it is light.
K is the counterfeit coin and it is heavy.
这些是我从网上找到的一些容易出错的数据,希望这些对于你调试程序会有帮助。
以上就是我的题解的全部。(下面的可以无视。)
因为在这个思路明白了后就很简单,但是,做这个题解中最大的难处就是如何让别人明白这个思路。所以,我就把这个题解写的比我当初在暑假中看到的那篇更详细。希望你不用琢磨一天。^_^为了到达这个目的,所以我就是把每次比较过程中偏了再偏的那种情况描述成“罪刑”。我只是希望这样会更好理解,这个解题的思路。如果你因为这个名词把你弄得更混乱了,好吧.........抱歉。。。。。。。
324

被折叠的 条评论
为什么被折叠?



