百炼 假币问题
题目链接:
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枚硬币,因此可以把所有硬币的所有状态都枚举一遍,对每一种假设的情况进行验证:若是某种假设符合输入的三个条件,那么该假设就是成立的。

1 #include<stdio.h> 2 int status[12]={0};//表示12枚硬币的真假状态:0为真,-1为假币且假币较轻,1为假币且假币较重 3 char left[3][7],right[3][7],result[3][7]; 4 bool Balanced();//判断某种假设是否合理 5 int main() 6 { 7 int i,num; 8 scanf("%d",&num); 9 while(num--) 10 { 11 for(i=0;i<3;i++) 12 scanf("%s %s %s",left[i],right[i],result[i]); 13 for(i=0;i<12;i++) status[i]=0;//开始的时候,假设全部硬币都是真硬币。 14 for(i=0;i<12;i++) 15 { 16 status[i]=1;//假设第i枚硬币是假币且假币较重 17 if(Balanced())//检验该种假设是否合理 18 break; //若合理则已经得到答案,结束循环 19 20 status[i]=-1;//假设第i枚硬币是假币且假币较轻 21 if(Balanced())//检验该种假设是否合理 22 break; //若合理则已经得到答案,结束循环 23 24 status[i]=0;//上述两种假设都不合理的话,第i枚硬币为真硬币。 25 } 26 27 printf("%c is the counterfeit coin and it is %s.\n",i+'A',status[i]==1?"heavy":"light"); 28 /**/ 29 } 30 31 return 0; 32 } 33 34 bool Balanced()//判断某种假设是否合理:合理则返回true,否则返回false. 35 { 36 int i,k,leftW,rightW; 37 for(i=0;i<3;i++)//依次检验三条规则 38 { 39 leftW=rightW=0; 40 for(k=0;left[i][k]!='\0';k++) 41 { 42 leftW+=status[left[i][k]-'A']; 43 rightW+=status[right[i][k]-'A']; 44 } 45 if(leftW>rightW&&result[i][0]!='u') return false; 46 if(leftW==rightW&&result[i][0]!='e') return false; 47 if(leftW<rightW&&result[i][0]!='d') return false; 48 } 49 return true; 50 }
第二个代码
来源:北大郭炜老师。道理都一样,只是上面那段代码理解起来似乎比较好理解一点。
对于每一枚硬币先假设它是轻的,看这样是否符合称量结果。如果符合,问题即解决。如果不符合,就假设它是重的,看是否符合称量结果。
把所有硬币都试一遍,一定能找到特殊硬币。
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 char Left[3][7]; //天平左边硬币 5 char Right[3][7]; //天平右边硬币 6 char result[3][7]; //称量结果 7 bool IsFake(char c,bool light);//light为真表示假设假币为轻,否则表示假设假币为重 8 int main() 9 { 10 int t; 11 cin >> t; 12 while(t--) 13 { 14 for(int i = 0;i < 3; ++i) cin >> Left[i] >> Right[i] >> result[i]; 15 for(char c='A'; c<='L';c++) 16 { 17 if( IsFake(c,true) )//假设c这个硬币为假硬币而且它比真硬币轻 18 { 19 cout << c << " is the counterfeit coin and it is light.\n"; 20 break; 21 } 22 else if( IsFake(c,false) )//假设c这个硬币为假硬币而且它比真硬币重 23 { 24 cout << c << " is the counterfeit coin and it is heavy.\n"; 25 break; 26 } 27 } 28 } 29 return 0; 30 } 31 bool IsFake(char c,bool light)//light 为真表示假设假币为轻,否则表示假设假币为重 32 { 33 for(int i = 0;i < 3; ++i) 34 { 35 char * pLeft,*pRight; //指向天平两边的字符串 36 if(light) 37 { 38 pLeft = Left[i]; 39 pRight = Right[i]; 40 } 41 else 42 { 43 pLeft = Right[i]; 44 pRight = Left[i]; 45 } 46 47 switch(result[i][0]) 48 { 49 case 'u': 50 if ( strchr(pRight,c) == NULL) return false; 51 break; 52 case 'e': 53 if( strchr(pLeft,c) || strchr(pRight,c)) return false; 54 break; 55 case 'd': 56 if ( strchr(pLeft,c) == NULL) return false; 57 break; 58 } 59 } 60 return true; 61 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App