POJ 1013 Counterfeit Dollar

题目: 有12枚硬币(标记为A-L),其中有1枚是假币,但不知道假币比真币更轻或更重。Sally借助于天平,设计出一种方案,可以恰好三次测量出谁是假币、比真币更轻或更重。要求你帮助Sally,根据她的测量数据,计算出谁是假币、比真币更轻还是更重。例如一组测量数据为:

ABCD EFGH even

ABCI EFJK up

ABIJ EFGH even

注意:天平左右的硬币数量总是相等的。

可以计算得出K是假币,且比真币更轻。

思路:从12个一样的钱币中找出一个未知重量的假币,称3次,给出结果,判断假币及其相对重量。
      用模拟的方法很容易想到排除法,即分情况讨论:
            当结果为even时,说明称上的几个钱币一定是真币
            当结果为up时,说明其余的钱币一定是真币,并且左边钱币中有一个重的或者右边钱币中有一个轻的
            当结果为down时,说明其余的钱币一定是真币,并且左边钱币中有一个轻的或者右边钱币中有一个重的
      模拟的方法就是用一个数组记录每个钱币的状态,初始为-1,如果一定为真币记为0,如果可能较重记为2,如果可能较轻记为1,最后只要判断大于0的钱币一定为假币,而相应的状态表示它的相对重量。
      可是实现时要考虑很多种细节,最重要的一点就是加一个记录上次状态的数组,因为如果上次判断一个钱币为真币,则不论下次结果如何,它还应当是真币;如果上次判断它可能较轻,而本次判断它可能较重,则它一定是真币!用循环及判断可做出来。

个人感觉:这道题刚开始我没看明白是什么意思,然后又看了题目的中文翻译,才理解了一点,但是还是没能全部理解清楚。所以参考了下网友的算法,觉得很容易,就是我用的这个算法。有个是用指针的算法,但是指针比较麻烦,所以我用了这种比较理解起来比较简单的算法。

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int main()
{
    int n, i, j, b, l;
    int real[16], t[16];
    char left[9], right[9], r[5];
    char s[3][17]= {"ABCDEFGHIJKL","light","heavy"};
    cin>>n;
    while(n--)
    {
        memset(real,-1,sizeof(real));
        for(i=0;i<3;i++)
        {
            cin>>left>>right>>r;
            b=strcmp(r,"even");
            l=strlen(left);
            if(b==0)
            {
                for( j= 0; j< l; j++ )
                    real[left[j]-'A']= real[right[j]-'A']= 0;
            }
            else if(b==-1)
            {
                memcpy(t,real,sizeof(real));
                memset(real,0,sizeof(real));
                for( j= 0; j< l; j++ )
                    real[left[j]-'A']= 1, real[right[j]-'A']= 2;
                for( j= 0; j< 16; j++ )
                    if( t[j]>=0 && t[j]!=real[j] ) real[j]= 0;
            }
            else
            {
                memcpy(t,real,sizeof(real));
                memset(real,0,sizeof(real));
                for( j= 0; j< l; j++ )
                    real[left[j]-'A']= 2, real[right[j]-'A']= 1;
                for( j= 0; j< 16; j++ )
                    if( t[j]>=0 && t[j]!=real[j] ) real[j]= 0;
            }
        }
        for( i= 0; i< 16; i++ )
            if( real[i]> 0 )
printf("%c is the counterfeit coin and it is %s.\n",s[0][i],s[real[i]]);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值