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是假的,代入判断1k不出现,那么两边重量应相等,成立。继续称量2k出现在右边,结果是UP,亦成立,且据此知道k是较轻的,因此k在右边,而天平右边翘起。下面进行判断3

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

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

具体代码如下:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 char left[3][7], right[3][7];
  6 char result[3][6];
  7 int a[15];
  8 int w;
  9 
 10 int judge(char ch)
 11 {
 12     int r1, r2;
 13     int i;
 14     int a[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                 return 0;
 23             else if (r2  == 0)
 24                 a[i] = 1;
 25             else 
 26                 a[i] = -1;
 27         }
 28         else if (strchr(right[i], ch) != NULL)
 29         {
 30             if (r1 == 0)
 31                 return 0;
 32             else if (r2 == 0)
 33                 a[i] = -1;
 34             else 
 35                 a[i] = 1;
 36         }
 37         else
 38         {
 39             if (r1 != 0)
 40                 return 0;
 41             a[i] = 3;
 42         } 
 43     }
        /*判断结果是否一致*/
 44     if (a[0!= 3)
 45         w = a[0];
 46     else if (a[1!= 3)
 47         w = a[1];
 48     else if (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                 return 0;
 55         }
 56     }
 57     return 1;
 58 }
 59 int main(void)
 60 {
 61     int n;
 62     int i;
 63     char *p;
 64     char ch;
 65     int r;
 66     scanf("%d%*c"&n);    
 67     while (n--)
 68     {
 69         memset(a, 0sizeof(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 (*!= '\0')
 77                 {
 78                     a[*p-'A'= 1;
 79                     ++p;
 80                 }
 81                 p = right[i];
 82                 while (*!= '\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                 else
101                 {
102                     printf("%c is the counterfeit coin and it is light.\n", ch);
103                 }
104                 break;
105             }
106         }
107     }
108     return 0;
109 }


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


posts - 12, comments - 1, trackbacks - 0, articles - 1

Copyright © 李东亮