题目链接:

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;
}

最新文章

  1. break 的一个“高级用法”(转)
  2. php修改指定文件的指定内容
  3. Google 面试题和详解
  4. codeforces195c
  5. JavaScript Patterns 3.2 Custom Constructor Functions
  6. Eclipse安装插件支持jQuery智能提示
  7. python数组的使用
  8. php中的字符串和正则表达式
  9. C++基本要点复习--------coursera程序设计实习(PKU)的lecture notes
  10. MySql优化方案
  11. 边记边学PHP-(十五)MySQL数据库基础操作2
  12. go语言实现遍历目录,及查找特定的文件类型
  13. &quot;R6002 floating point support not loaded&quot;问题分析
  14. 不看就亏了:DELL EqualLogic PS6100详解及数据恢办法
  15. XUnit 依赖注入
  16. 好大一个坑: EF Core 异步读取大字符串字段比同步慢100多倍
  17. python 全局变量
  18. tomcat服务器-谷歌等浏览器-加载本地图片等资源-报not allowed to load local resource的错误解决办法。
  19. k8s 高级调度 亲和力和反亲和力、绑定标签、污点容忍污点
  20. linux下vmstat命令详解

热门文章

  1. [转]Linux系统下如何查看及修改文件读写权限
  2. 启明星手机版安卓android会议室预定系统 V1.0发布
  3. Netty Message RefCount
  4. Spring Scheduler定时任务 + Quartz
  5. Java switch 枚举
  6. Hadoop集群WordCount运行详解(转)
  7. easyui基于web的打印实现 .
  8. 如何: 重命名在 IIS 6.0 中的虚拟目录
  9. 强制windows系统重启at命令
  10. thinkphp生成的验证码不显示问题解决