题目链接:

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

百炼  假币问题  http://bailian.openjudge.cn/practice/2692/

题目大意

有12枚硬币。其中有11枚真币和1枚假币。假币和真币重量不同,但不知道假币比真币轻还是重。现在,用一架天平称了这些币三次,告诉你称的结果,请你找出假币并且确定假币是轻是重(数据保证一定能找出来)。

输入
第一行是测试数据组数。
每组数据有三行,每行表示一次称量的结果。银币标号为A-L。每次称量的结果用三个以空格隔开的字符串表示:天平左边放置的硬币、天平右边放置的硬币、平衡状态。其中平衡状态用``up'', ``down'', 或 ``even''表示, 分别为右端高、右端低和平衡。天平左右的硬币数总是相等的。

输出
输出哪一个标号的银币是假币,并说明它比真币轻还是重 。

输入样例
1
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
输出样例
K is the counterfeit coin and it is light.

解题思路

第一种代码

每一枚硬币有三种状态:较重的假币、较轻的假币、真硬币。

由于只有一枚假币,且总共只有12枚硬币,因此可以把所有硬币的所有状态都枚举一遍对每一种假设的情况进行验证:若是某种假设符合输入的三个条件,那么该假设就是成立的。

 #include<stdio.h>
int status[]={};//表示12枚硬币的真假状态:0为真,-1为假币且假币较轻,1为假币且假币较重
char left[][],right[][],result[][];
bool Balanced();//判断某种假设是否合理
int main()
{
int i,num;
scanf("%d",&num);
while(num--)
{
for(i=;i<;i++)
scanf("%s %s %s",left[i],right[i],result[i]);
for(i=;i<;i++) status[i]=;//开始的时候,假设全部硬币都是真硬币。
for(i=;i<;i++)
{
status[i]=;//假设第i枚硬币是假币且假币较重
if(Balanced())//检验该种假设是否合理
break; //若合理则已经得到答案,结束循环 status[i]=-;//假设第i枚硬币是假币且假币较轻
if(Balanced())//检验该种假设是否合理
break; //若合理则已经得到答案,结束循环 status[i]=;//上述两种假设都不合理的话,第i枚硬币为真硬币。
} printf("%c is the counterfeit coin and it is %s.\n",i+'A',status[i]==?"heavy":"light");
/**/
} return ;
} bool Balanced()//判断某种假设是否合理:合理则返回true,否则返回false.
{
int i,k,leftW,rightW;
for(i=;i<;i++)//依次检验三条规则
{
leftW=rightW=;
for(k=;left[i][k]!='\0';k++)
{
leftW+=status[left[i][k]-'A'];
rightW+=status[right[i][k]-'A'];
}
if(leftW>rightW&&result[i][]!='u') return false;
if(leftW==rightW&&result[i][]!='e') return false;
if(leftW<rightW&&result[i][]!='d') return false;
}
return true;
}

来自刘家瑛《算法基础与在线实践》

第二个代码

来源:北大郭炜老师。道理都一样,只是上面那段代码理解起来似乎比较好理解一点。

对于每一枚硬币先假设它是轻的,看这样是否符合称量结果。如果符合,问题即解决。如果不符合,就假设它是重的,看是否符合称量结果。

把所有硬币都试一遍,一定能找到特殊硬币。

 #include <iostream>
#include <cstring>
using namespace std;
char Left[][]; //天平左边硬币
char Right[][]; //天平右边硬币
char result[][]; //称量结果
bool IsFake(char c,bool light);//light为真表示假设假币为轻,否则表示假设假币为重
int main()
{
int t;
cin >> t;
while(t--)
{
for(int i = ;i < ; ++i) cin >> Left[i] >> Right[i] >> result[i];
for(char c='A'; c<='L';c++)
{
if( IsFake(c,true) )//假设c这个硬币为假硬币而且它比真硬币轻
{
cout << c << " is the counterfeit coin and it is light.\n";
break;
}
else if( IsFake(c,false) )//假设c这个硬币为假硬币而且它比真硬币重
{
cout << c << " is the counterfeit coin and it is heavy.\n";
break;
}
}
}
return ;
}
bool IsFake(char c,bool light)//light 为真表示假设假币为轻,否则表示假设假币为重
{
for(int i = ;i < ; ++i)
{
char * pLeft,*pRight; //指向天平两边的字符串
if(light)
{
pLeft = Left[i];
pRight = Right[i];
}
else
{
pLeft = Right[i];
pRight = Left[i];
} switch(result[i][])
{
case 'u':
if ( strchr(pRight,c) == NULL) return false;
break;
case 'e':
if( strchr(pLeft,c) || strchr(pRight,c)) return false;
break;
case 'd':
if ( strchr(pLeft,c) == NULL) return false;
break;
}
}
return true;
}

POJ1013 称硬币的更多相关文章

  1. POJ1013称硬币【枚举】

    Counterfeit Dollar Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 52474   Accepted: 16 ...

  2. 枚举-称硬币POJ1013

    #include <iostream> #include<string.h> using namespace std; char Lleft[][]; char Lright[ ...

  3. 算法题----称硬币: 2n(并不要求n是2的幂次方)个硬币,有两个硬币重量为m+1, m-1, 其余都是m 分治 O(lgn)找出假币

    Description: 有2n个硬币和一个天平,其中有一个质量是m+1, 另一个硬币质量为m-1, 其余的硬币质量都是m. 要求:O(lgn)时间找出两枚假币 注意: n不一定是2的幂次方 算法1: ...

  4. C++基础算法学习——猜假币

    有12枚硬币.其中有11枚真币和1枚假币.假币和真币重量不同,但不知道假币比真币轻还是重.现在,用一架天平称了这些币三次,告诉你称的结果,请你找出假币并且确定假币是轻是重(数据保证一定能找出来).例题 ...

  5. ACM训练计划建议(写给本校acmer,欢迎围观和指正)

    ACM训练计划建议 From:freecode#  Date:2015/5/20 前言: 老师要我们整理一份训练计划给下一届的学弟学妹们,整理出来了,费了不少笔墨,就也将它放到博客园上供大家参考. 菜 ...

  6. 【POJ水题完成表】

    题目 完成情况 poj1000:A+B problem 完成 poj1002:电话上按键对应着数字.现在给n个电话,求排序.相同的归一类 完成 poj1003:求最小的n让1+1/2+1/3+...+ ...

  7. ACM训练计划建议(转)

    ACM训练计划建议 From:freecode#  Date:2015/5/20 前言: 老师要我们整理一份训练计划给下一届的学弟学妹们,整理出来了,费了不少笔墨,就也将它放到博客园上供大家参考. 菜 ...

  8. (BruteForce)暴力破解经典题目总结

    在算法竞赛中,很多问题是来不及用数学公式推导出来的.或者说根本就找不到数学规律,这时我们就需要使用枚举来暴力破解. 不过枚举也是需要脑子的,一味的暴力只能超时.因此我这里选择了几道mooc上经典的题目 ...

  9. codes often WA

    枚举: 1.完美立方 #include<iostream> #include <cstdio> using namespace std; int main() { int N; ...

随机推荐

  1. 如何设置浏览器禁止使用UC浏览器

    通过UA可以判断浏览器是否是UC浏览器 if(navigator.userAgent.indexOf('UCBrowser')>-1) {  alert("当前浏览器不支持本站,建议更 ...

  2. [填坑]解决"Your MaintenanceTool appears to be older than 3.0.2. ."问题

    之前我写过QT5.9版本在更新组件时出现“要继续此操作,至少需要一个有效且已启用的储存库”问题,得到了网友的热心转载,说明遇到此问题的人不在少数. 原文地址:https://blog.csdn.net ...

  3. C#邮件发送(最坑爹的邮箱-QQ邮箱)

    最近工作挺清闲的,有空的时候陪妹子出去玩玩,自己看看小说,看看电影,日子过的挺欢乐的,这个星期幡然悔悟,代码才是我的最爱,做点小东西,就写个邮件发送程序.说的邮件发送相信工作过基本上都会用到过,用户注 ...

  4. 分布式高并发物联网(车联网-JT808协议)平台架构方案

    技术支持QQ:78772895 1.车载终端网关采用mina/netty+spring架构,独立于其他应用,主要负责维护接入终端的tcp链接.上行以及下行消息的解码.编码.流量控制,黑白名单等安全控制 ...

  5. Delphi获取默认打印机名称及端口

    Delphi获取默认打印机名称及端口 在前段时间写的收银系统中由于目前市场上很多电脑主板上已经没有并口,而POS机却又需要并口,所以目前需要用PCI转接卡,这个就导致不同门店使用的端口就有可能不同,这 ...

  6. TextEdit 只能输入数字(0-9)的限制

    MaskType="RegEx" MaskUseAsDisplayFormat="True" Mask="[0-9]*" <dxe:T ...

  7. Linux Kernel 2:用户空间的初始化

    上篇我们知道,kernel初始化后将启动init进程,那么这个进程将干些什么呢?除此之外,kernel还需要做些什么事情呢?(想想文件系统.根存储设备是在什么时候初始化的呢?) 先从文件系统初始化说起 ...

  8. Linux系统中关于Sqlite3中文乱码问题及解决办法

    新做的一个项目在本地(Win8)测试时没有问题,但传到服务器(Linux)时从Sqlite3数据库查询到的数据中文却是乱码(数据库中是正常的) 将php文件.html文件都设置成统一的utf8还是一样 ...

  9. PHP构造函数的重载

    由于PHP是弱类型语言,因此函数的输入参数类型无法确定(可以使用类型暗示,但是类型暗示无法用在诸如整型,字符串之类的标量类型上),并且对于一个函数,比如只定义了3个输入参数,PHP却运行调用的时候输入 ...

  10. selenium之 chromedriver与chrome版本映射表(更新至v2.38)

    https://blog.csdn.net/huilan_same/article/details/51896672 看到网上基本没有最新的chromedriver与chrome的对应关系表,便兴起整 ...