hdu 1482 Counterfeit Dollar

来源:互联网 发布:excel数据批量打印 编辑:程序博客网 时间:2024/06/03 19:43

Counterfeit Dollar

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 274    Accepted Submission(s): 117


Problem Description
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
1ABCD EFGH evenABCI EFJK upABIJ EFGH even
 

Sample Output
K is the counterfeit coin and it is light.
 

Source
East Central North America 1998
 

Recommend
xhd
 

题目大意说有12个银币其中一个是假冒伪劣的。要你把它找出来。题目会给三次称量(保证左右两端银币数目相同)天平左端的状态。

要求根据给出的数据找出假冒伪劣银币是哪一个。重量是轻了还是重了。


我们假定那假的是重的。

可以证明的是

①.假冒伪劣银币有一个特点就是它永远在down的那边。

②.如果一个银币既在down出现过又在up出现过那么它一定是真的,

③.如果天平状态为even则两盘的银币都是真的。(因为只有一个假硬币)
天平只有三种状态。一次称量平衡,两次称量平衡。和0次称量平衡。

三次平衡是不可能滴(如果三次平衡虽然可能找出假币但是不能判断其轻重)

意思就是说如果0次平衡那么down三次的硬币就是重的。(题目保证有解所以其它dwon3次的可以通过前面的测量或后面的测量排除)

同侧down三次则不能确定谁是假的不满足唯一性。异侧down3次。假定a和b异侧down三次且a不能确定是否为真那么相当于开始在天平两端放上a和b。然后在两端加上等重物。当然不能确定谁是假的啦。down两次同侧down两次down端只能有一个未知真假(唯一性).异侧down2次同异侧down三次.

down 一次的情况最简单。肯定只有一个不能确定(通过前面给出定理)才有解呀。

代码只是粗略的写了下。有点长。有时间优化下。

#include <stdio.h>#include<string.h>int abs(int x){    return x<0?-x:x;}int main(){    int ok[13],n,p,i,j,ans,mi;//ok记录钱币真假    //有四种状态4,正,负,0;4代表未知正表示称重down的次数.负为up的次数    //0为确定为真银币    char l[10],r[10],w[10];//l记录左盘的硬币。r记录右盘的银币。w记录天平状态    scanf("%d",&n);    getchar();    while(n--)    {        for(i=0;i<=12;i++)//初始化为未知            ok[i]=4;        for(i=0;i<3;i++)        {            scanf("%s%s%s",l,r,w);            if(!strcmp(w,"up"))//如果左端轻            {                for(j=0;l[j]!='\0';j++)                {                    p=l[j]-'A';//映射于ok对应位置                    if(ok[p]==4)                        ok[p]=1;                    else if(ok[p]<0)                        ok[p]=0;                    else if(ok[p]>0)                        ok[p]++;                }                for(j=0;r[j]!='\0';j++)                {                    p=r[j]-'A';                    if(ok[p]==4)                        ok[p]=-1;                    else if(ok[p]>0)                        ok[p]=0;                    else if(ok[p]<0)                        ok[p]--;                }            }            else if(!strcmp(w,"even"))            {                for(j=0;l[j]!='\0';j++)                {                    p=l[j]-'A';                    ok[p]=0;                }                for(j=0;r[j]!='\0';j++)                {                    p=r[j]-'A';                    ok[p]=0;                }            }            else            {                for(j=0;l[j]!='\0';j++)                {                    p=l[j]-'A';                    if(ok[p]==4)                        ok[p]=-1;                    else if(ok[p]>0)                        ok[p]=0;                    else if(ok[p]<0)                        ok[p]--;                }                for(j=0;r[j]!='\0';j++)                {                    p=r[j]-'A';                    if(ok[p]==4)                        ok[p]=1;                    else if(ok[p]<0)                        ok[p]=0;                    else if(ok[p]>0)                        ok[p]++;                }            }        }        mi=0;        for(j=0;j<=12;j++)            if(ok[j]!=4&&abs(ok[j])>mi)                mi=abs(ok[j]),ans=j;        if(ok[ans]>0)            printf("%c is the counterfeit coin and it is heavy.\n",'A'+ans);        else            printf("%c is the counterfeit coin and it is light.\n",'A'+ans);    }    return 0;}/*1AB CD upEC BD upAE CD up*/

优化后的代码变短了不过貌似耗时多了一丁点。

#include <stdio.h>#include<string.h>int ok[13];//ok记录钱币真假有四种状态4,正,负,0;4代表未知正表示称重down的次数.负为up的次数    //0为确定为真银币int abs(int x){    return x<0?-x:x;}void solve(char *l,char *r)//解决左重右轻的情况{    int j,p;    for(j=0; l[j]!='\0'; j++)    {        p=l[j]-'A';//映射于ok对应位置        if(ok[p]==4)            ok[p]=1;        else if(ok[p]<0)            ok[p]=0;        else if(ok[p]>0)            ok[p]++;    }    for(j=0; r[j]!='\0'; j++)    {        p=r[j]-'A';        if(ok[p]==4)            ok[p]=-1;        else if(ok[p]>0)            ok[p]=0;        else if(ok[p]<0)            ok[p]--;    }}int main(){    int n,p,i,j,ans,mi;    char l[10],r[10],w[10];//l记录左盘的硬币。r记录右盘的银币。w记录天平状态    scanf("%d",&n);    getchar();    while(n--)    {        for(i=0; i<12; i++) //初始化为未知            ok[i]=4;        for(i=0; i<3; i++)        {            scanf("%s%s%s",l,r,w);            if(!strcmp(w,"up"))//如果左重右轻右端轻            solve(l,r);            else if(!strcmp(w,"even"))//解决两端等重情况            {                for(j=0; l[j]!='\0'; j++)                {                    p=l[j]-'A';                    ok[p]=0;                }                for(j=0; r[j]!='\0'; j++)                {                    p=r[j]-'A';                    ok[p]=0;                }            }            else               solve(r,l);//左轻右重。交换位置后变成左重右轻        }        mi=0;        for(j=0; j<12; j++)            if(ok[j]!=4&&abs(ok[j])>mi)                mi=abs(ok[j]),ans=j;        if(ok[ans]>0)            printf("%c is the counterfeit coin and it is heavy.\n",'A'+ans);        else            printf("%c is the counterfeit coin and it is light.\n",'A'+ans);    }    return 0;}/*2AB CD upEC BD upAE CD up*/



原创粉丝点击