C语言实现STL静态链表类,blueslee

Counterfeit

Dollar

该题ZOJ题号为1184,POJ题号为1013.

题目描述如下:

Sally Jones has a dozen Voyageur silver

dollars. However, only eleven of the coins are true silver dollars; one coin is

counterfeit even though its color and size make it indistinguishable from the

real silver dollars. The counterfeit coin has a different weight from the other

coins but Sally does not know if it is heavier or lighter than the real coins.

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.

Input

The first line of input is an integer n (n > 0) specifying the number of

cases to follow. Each case consists of three lines of input, one for each

weighing. Sally has identified each of the coins with the letters A-L.

Information on a weighing will be given by two strings of letters and then one

of the words ``up'', ``down'', or ``even''. The first string of letters will

represent the coins on the left balance; the second string, the coins on the

right balance. (Sally will always place the same number of coins on the right

balance as on the left balance.) The word in the third position will tell

whether the right side of the balance goes up, down, or remains even.

Output

For each case, the output will identify the counterfeit coin by its letter and

tell whether it is heavy or light. The solution will always be uniquely

determined.

Sample Input

1

ABCD EFGH even

ABCI EFJK up

ABIJ EFGH even

Sample Output

K is the counterfeit coin and it is light.

【分析】该题属于枚举范畴。没有比较巧妙的可以一步到位求出结果的方法,可以一次枚举这12枚钱币,假设其为假,然后代入到3次称量判断中,如果使三次判断都成立且判断结果相同,那么毫无疑问这枚钱币是假的。首先可以进行预处理,比较结果为EVEN的可以判定两边的钱币都是真的,不必参与到枚举中来。对于上面的输入用例,假设K是假的,代入判断1,k不出现,那么两边重量应相等,成立。继续称量2,k出现在右边,结果是UP,亦成立,且据此知道k是较轻的,因此k在右边,而天平右边翘起。下面进行判断3

,k没有出现在天平两边,而且结果为even成立。通过三次称量判断,且结果一致,可以肯定k就是假币,且较轻。为了说明为题,对于上例假设L是假币。代入称量1,L不出现,结果even成立,称量2,L不出现,结果为up不成立,因为只有一枚假币,现假设L为假币,而在L不出现的情况下天平不平衡,故L不是假币。按照上述算法进行枚举,遇到可以肯定是假币的货币时算法终止。

需要注意的是当假设一枚硬币为假且通过三次称量时,需要判断三次称量k的轻重情况是否一致,如果一次推得该硬币较轻,而另一次却判断该硬币较重,那么该硬币肯定不是假币。在判断是需要注意当左右两边都不出现假设为假的硬币时,需要特殊处理,不能简单的比较3次硬币轻重是否相同,在左右两边都不出现该硬币的情况下,不应该把这次测量纳入比较的范畴。除此之外需要的就是细心了,本人因为打印的时候多打印了个the,WA了6次,检查了半个多小时,有种欲哭无泪的感觉。

具体代码如下:

1 #include2 #include3 #include4 5 charleft[3][7], right[3][7];6 charresult[3][6];7 inta[15];8 intw;9 10 intjudge(charch)11 {12 intr1, r2;13 inti;14 inta[3];

/*对当前假设的硬币进行判断*/15 for(i=0; i<3;++i)16 {17 r1=strcmp(result[i],"even");18 r2=strcmp(result[i],"up");19 if(strchr(left[i], ch)!=NULL)20 {21 if(r1==0)22 return0;23 elseif(r2==0)24 a[i]=1;25 else26 a[i]=-1;27 }28 elseif(strchr(right[i], ch)!=NULL)29 {30 if(r1==0)31 return0;32 elseif(r2==0)33 a[i]=-1;34 else35 a[i]=1;36 }37 else38 {39 if(r1!=0)40 return0;41 a[i]=3;42 }43 }

/*判断结果是否一致*/44 if(a[0]!=3)45 w=a[0];46 elseif(a[1]!=3)47 w=a[1];48 elseif(a[2]!=3)49 w=a[2];50 for(i=0; i<3;++i)51 {52 if(a[i]!=3&&a[i]!=w)53 {54 return0;55 }56 }57 return1;58 }59 intmain(void)60 {61 intn;62 inti;63 char*p;64 charch;65 intr;66 scanf("%d%*c",&n);67 while(n--)68 {69 memset(a,0,sizeof(a));70 for(i=0; i<3;++i)71 {72 scanf("%s%s%s", left[i], right[i], result[i]);73 if(strcmp (result[i],"even")==0)74 {75 p=left[i];76 while(*p!='\0')77 {78 a[*p-'A']=1;79 ++p;80 }81 p=right[i];82 while(*p!='\0')83 {84 a[*p-'A']=1;85 ++p;86 }87 }88 }89 for(ch='A'; ch<='L';++ch)90 {91 if(a[ch-'A']==1)92 continue;93 r=judge(ch);94 if(r==1)95 {96 if(w>0)97 {98 printf("%c is the counterfeit coin and it is heavy.\n", ch);99 }100 else101 {102 printf("%c is the counterfeit coin and it is light.\n", ch);103 }104 break;105 }106 }107 }108 return0;109 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值