8.3数学模型中包括多个变量的例子:称硬币

来源:互联网 发布:智能社javascript视频 编辑:程序博客网 时间:2024/06/05 13:26

问题定义:



赛利有 
12枚银币。其中有 11枚真币和1枚假币。假币看起来和真币没有区别,但是重量不同。但赛利不知道假币比真币轻还是重。于是他向朋友借了一架天平。朋友希望赛利称三次就能找出假币并且确定假币是轻是重。例如:如果赛利用天平称两枚硬币,发现天平平衡,说明两枚都是真的。如果赛利用一枚真币与另一枚银币比较,发现它比真币轻或重,说明它是假币。经过精心安排每次的称量,赛利保证在称三次后确定假币。


输入数据


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


输出要求:


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


输入样例 







ABCD EFGH even 


ABCI EFJK up 


ABIJ EFGH even 


输出样例 




K is the counterfeit coin and it is light.


解题思路


此题中赛利已经设计了正确的称量方案,保证从三组称量数据中能得到唯一的答案。答案可以用两个变量表示:x.假币的标号w.假币是比真币轻还是比真币重。x共有12种猜测;w有2种猜测。根据赛利设计的称量方案,(x,w )的24种猜测中,只有唯一的猜测与三组称量数据都不矛盾。因此,如果猜测 (x,w )满足下列条件,这个猜测就是要找的答案: 
 
在称量结果为"even''的天平两边,没有出现x ; 

如果w表示假币比真币轻,则在称量结果为"up'' 的天平右边一定出现x、在称量结果为"down''的天平左边一定出现x 如果w表示假币比真币重,则在称量结果为"up'' 的天平左边一定出现 
x、在称量结果为"down''的天平右边一定出现x。
具体实现时,要注意两点: 




1) 选择合适的算法,对于每一枚硬币x逐个试探: 
x比真币轻的猜测是否成立?猜测成立则进行输出。 
x比真币重的猜测是否成立?猜测成立则进行输出。 
2) 选择合适的数据结构
    以字符串数组存储称量的结果。每次称量时,天平左右最多有6枚硬币。因此,字符串的长度需要为7,最后一位存储字符串的结束符’\0’,便于程序代码中使用字符串操作函数。 


char left[3][7], right[3][7], result[3][7]; 


注意事项:

1.对于经常要用到的数据,先预处理

2.仔细分析问题,减少搜索空间

代码示例:

/***Declaration:The author of <<Accelerated C++>> has wrote in the end of that book: As you look for reading materimal, keep in mind that books on the shelf do not make you a better programmer. Ultimately, the only way to improve your programming is to write programs.>这些程序来自一些ACM书籍,作者只为提高编程能力,实现书中例题或练习。如有侵权,请联系作者,作者将立即删除。**联系邮箱:mingxinglai#gmail.com**/#include <stdio.h>#include <string.h>char left[3][7], right[3][7], result[3][5];bool isHeavy( char );bool isLight( char );int main(int argc, char* argv[]){int n;char c;scanf("%d", &n);while( n-- ){for( int i = 0; i < 3; i++)scanf("%s%s%s", left[i], right[i], result[i]);for( c = 'A'; c <= 'L'; c++ ){if( isLight( c ) ){printf("%c is the counterfeit coin and it is light.\n", c);break;}if( isHeavy( c ) ){printf("%c is the counterfeit coin and it is heavy.\n", c);break;}}}return 0;}bool isLight( char x ){int i;for( i = 0; i < 3; i++)switch( result[i][0] ){case 'u': if( strchr( right[i], x) == NULL) return false;break;case 'e': if( strchr( right[i], x) != NULL || strchr( left[i], x) != NULL ) return false;break;case 'd': if( strchr( left[i], x) == NULL ) return false;break;}return true;}bool isHeavy( char x ){int i;for( i = 0; i < 3; i++)switch( result[i][0] ){case 'u': if( strchr( left[i], x) == NULL) return false;break;case 'e': if( strchr( right[i], x) != NULL || strchr( left[i], x) != NULL ) return false;break;case 'd': if( strchr( right[i], x) == NULL ) return false;break;}return true;}