HDU 1482/ZOJ 1184/FOJ 1003/POJ 1013 Counterfeit Dollar

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1482

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1184

http://acm.fzu.edu.cn/problem.php?pid=1003

http://poj.org/problem?id=1013

原博文地址:http://blog.csdn.net/lyy289065406/article/details/6661421

题意:

有一打(12枚)硬币,其中有且仅有1枚假币,11枚真币

用A~L作为各个硬币的代号

假币可能比真币略轻,也可能略重

现在利用天枰,根据Input输入的3次称量,找出假币,并输出假币是轻还是重。

解题思路:

模拟法要考虑的情况较繁琐,可利用简单的逻辑推理进行解题。

注意Input一行代表一次称量,每行有三个字符串,分别为

Left   right     status

代表该次称量时,天枰左盘放的硬币、天枰右盘放的硬币、天枰右盘的状态

 

共三种状态:

Up:右盘上升,说明右盘可能有轻假币,也可能左盘有重假币。

Down:右盘下降,说明右盘可能有重假币,也可能左盘有轻假币。

Even:右盘与左盘平衡,由于假币有且仅有1枚,则说明此时天枰两边的硬币全为真币。

注意题目的字眼:

1、  有且仅有1枚假币

2、  假币相对于真币的重量,可能轻可能重

3、  只称量3次,且称量3次恰好且必能找到假币

4、  每次称量时天枰两边的硬币数目一样

5、  选取哪些硬币称量由input决定

 

从3、4、5可知,由于无法知道每次选取称量的硬币,那么3次称量可能只选用了几个硬币,也可能仅有一两个硬币没有选上,那么用模拟法去记录每次用于称量的硬币的状态(真假,其中假币又有轻重之分)并推导没有被称量的硬币状态(或状态变化)是很困难的,虽然人很容易做到这点,但计算机却很难去“推导”,因为称量硬币的方法是无规律的且非常多。

 

那么只能通过适当转化问题后用另一种有效的方法去解决。

 

虽然称量硬币的方法是无规律且未知的,但是称量硬币后的结果却只有3个,up、down和 even。且当出现even时,天枰两边的硬币必然都为真币,假币必定在余下的硬币之间(这是因为假币有且只有一枚),

那么我们就可以定义一个标记数组 bool flag[]去标记even时的真币,在以后的处理把他们排除在外。

而唯一难以处理的是up和down的状态,因为假币可能轻可能重,则这两种状态都无法得知究竟假币出现在天枰的哪边。

处理up和down状态方法:

当出现up或down状态时,天枰两边的所有硬币都应该被怀疑为假币(已标记必定为真币的硬币不必被怀疑)。

首先tt[]记录每个硬币的被怀疑程度,tt[i]=0表示该硬币i不被怀疑(即其可能为真币)。定义在up状态盘的硬币为“轻怀疑假币”,通过“--”操作加深其被怀疑为轻假币的程度,“负号”为轻假币的怀疑方向;在down状态盘的硬币为“重怀疑假币”,通过“++”操作加深其被怀疑为重假币的程度,“正号”为重假币的怀疑方向。

那么若一枚真币被怀疑为“轻假币”时,它就可能通过下次称量通过“++”操作取消嫌疑了。初始化所有硬币的怀疑程度均为0。

称量完毕后,找出被怀疑程度最大(注意取绝对值)的硬币,它就是假币。而当其怀疑方向为正时,则其为重假币。为负时,为轻假币。

代码:(与原博文不同有点丑)

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
   int n;
   char a1[8],b1[8],c1[8];
   char a2[8],b2[8],c2[8];
   char a3[8],b3[8],c3[8];
   int aa1,bb1,aa2,bb2,aa3,bb3;
   scanf("%d",&n);
   while(n--)
   {
       int tt[15]={0};
       bool flag[15]={false};
       scanf("%s %s %s",a1,b1,c1);
       scanf("%s %s %s",a2,b2,c2);
       scanf("%s %s %s",a3,b3,c3);
       aa1=strlen(a1);
       bb1=strlen(b1);
       aa2=strlen(a2);
       bb2=strlen(b2);
       aa3=strlen(a3);
       bb3=strlen(b3);
       if(c1[0]=='e')
       {
          for(int i=0;i<aa1;i++)
            flag[a1[i]-'A'+1]=true;
          for(int i=0;i<bb1;i++)
            flag[b1[i]-'A'+1]=true;
       }
       else
        if(c1[0]=='u')
       {
           for(int i=0;i<aa1;i++)
           {
               if(flag[a1[i]-'A'+1])
                tt[a1[i]-'A'+1]=0;
               else
                tt[a1[i]-'A'+1]++;
           }

           for(int i=0;i<bb1;i++)
             {
               if(flag[b1[i]-'A'+1])
                tt[b1[i]-'A'+1]=0;
               else
                tt[b1[i]-'A'+1]--;
           }
       }
       else
        if(c1[0]=='d')
       {
           for(int i=0;i<aa1;i++)
           {
               if(flag[a1[i]-'A'+1])
                tt[a1[i]-'A'+1]=0;
               else
                tt[a1[i]-'A'+1]--;
           }

           for(int i=0;i<bb1;i++)
             {
               if(flag[b1[i]-'A'+1])
                tt[b1[i]-'A'+1]=0;
               else
                tt[b1[i]-'A'+1]++;
           }
       }

       //............
        if(c2[0]=='e')
       {
          for(int i=0;i<aa2;i++)
           {
               flag[a2[i]-'A'+1]=true;
               tt[a2[i]-'A'+1]=0;
           }
          for(int i=0;i<bb2;i++)
          {
              flag[b2[i]-'A'+1]=true;
              tt[b2[i]-'A'+1]=0;
          }

       }
       else
        if(c2[0]=='u')
       {
           for(int i=0;i<aa2;i++)
           {
               if(flag[a2[i]-'A'+1])
                   tt[a2[i]-'A'+1]=0;
               else
                tt[a2[i]-'A'+1]++;
           }
          for(int i=0;i<bb2;i++)
           {
               if(flag[b2[i]-'A'+1])
                   tt[b2[i]-'A'+1]=0;
               else
                tt[b2[i]-'A'+1]--;
           }
       }
       else
        if(c2[0]=='d')
       {
            for(int i=0;i<aa2;i++)
           {
               if(flag[a2[i]-'A'+1])
                   tt[a2[i]-'A'+1]=0;
               else
                tt[a2[i]-'A'+1]--;
           }
          for(int i=0;i<bb2;i++)
           {
               if(flag[b2[i]-'A'+1])
                   tt[b2[i]-'A'+1]=0;
               else
                tt[b2[i]-'A'+1]++;
           }
       }
    //,,,,,,,,,,,,,
    if(c3[0]=='e')
       {
          for(int i=0;i<aa3;i++)
            {
                flag[a3[i]-'A'+1]=true;
                tt[a3[i]-'A'+1]=0;
            }
          for(int i=0;i<bb3;i++)
          {
              flag[b3[i]-'A'+1]=true;
               tt[b3[i]-'A'+1]=0;
          }

       }
       else
        if(c3[0]=='u')
       {
           for(int i=0;i<aa3;i++)
           {
               if(flag[a3[i]-'A'+1])
                   tt[a3[i]-'A'+1]=0;
               else
                tt[a3[i]-'A'+1]++;
           }
          for(int i=0;i<bb3;i++)
           {
               if(flag[b3[i]-'A'+1])
                   tt[b3[i]-'A'+1]=0;
               else
                tt[b3[i]-'A'+1]--;
           }
       }
       else
        if(c3[0]=='d')
       {
            for(int i=0;i<aa3;i++)
           {
               if(flag[a3[i]-'A'+1])
                   tt[a3[i]-'A'+1]=0;
               else
                tt[a3[i]-'A'+1]--;
           }
          for(int i=0;i<bb3;i++)
           {
               if(flag[b3[i]-'A'+1])
                   tt[b3[i]-'A'+1]=0;
               else
                tt[b3[i]-'A'+1]++;
           }
       }
//...................
     int tt2[15];
     char tt3[15]={'A','A','B','C','D','E','F','G','H','I','J','K','L'};
     for(int i=1;i<=12;i++)
        {
            tt2[i]=tt[i];
            tt[i]=abs(tt[i]);
        }
        int maxx=-2;
           int g;
           for(int i=1;i<=12;i++)
              {
                  if(maxx<tt[i])
                  {
                      maxx=tt[i];
                      g=i;
                  }
              }
           if(tt2[g]<0)
                printf("%c is the counterfeit coin and it is light.\n",tt3[g]);
           else
                 printf("%c is the counterfeit coin and it is heavy.\n",tt3[g]);
   }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值