![]() ![]() |
|
C趣味程序百例(16)迷语博士的难题(2) | |
作者:佚名 文章来源:不详 点击数 更新时间:2008/4/18 13:59:07 文章录入:杜斌 责任编辑:杜斌 | |
|
|
两面族是荒岛上的一个新民族,他们的特点是说话真一句假一句且真假交替。如果第一句为真,则第二句是假的;如果第一句为假的,则第二句就是真的,但是第一句是真是假没有规律。 迷语博士遇到三个人,知道他们分别来自三个不同的民族:诚实族、说谎族和两面族。三人并肩站在博士前面。 博士问左边的人:“中间的人是什么族的?”,左边的人回答:“诚实族的”。 博士问中间的人:“你是什么族的?”,中间的人回答:“两面族的”。 博士问右边的人:“中间的人究竟是什么族的?”,右边的人回答:“说谎族的”。 请问:这三个人都是哪个民族的? *问题分析与算法设计 这个问题是两面族问题中最基本的问题,它比前面只有诚实族和说谎族的问题要复杂。解题时要使用变量将这三个民族分别表示出来。 令:变量A=1表示:左边的人是诚实族的(用C语言表示为A); 变量B=1表示:中间的人是诚实族的(用C语言表示为B); 变量C=1表示:右边的人是诚实族的(用C语言表示为C); 变量AA=1表示:左边的人是两面族的(用C语言表示为AA); 变量BB=1表示:中间的人是两面族的(用C语言表示为BB); 变量CC=1表示:右边的人是两面族的(用C语言表示为CC); 则左边的人是说谎族可以表示为:A!=1且AA!=1 (不是诚实族和两面族的人) 用C语言表示为:!A&&!AA 中间的人是说谎族可以表示为:B!=1且BB!=1 用C语言表示为:!B&&!BB 右边的人是说谎族可以表示为:C!=0且CC!=1 用C语言表示为:!C&&!CC 根据题目中“三人来自三个民族”的条件,可以列出: a+aa!=2&&b+bb!=2&&c+cc!=2 且 a+b+c==1&&aa+bb+cc==1 根据左边人的回答可以推出:若他们是诚实族,则中间的人也是诚实族;若他不是诚实族,则中间的人也不是诚实族。以上条件可以表示为: c&&!b&&!bb||(!c&&!cc)&&(b||bb)||!c&&cc 将全部逻辑条件联合在一起,利用穷举的方法求解,凡是使上述条件同时成立的变量取值就是题目的答案。 *程序与程序注释 #include<stdio.h> void main() { int a,b,c,aa,bb,cc; for(a=0;a<=1;a++) /*穷举全部情况*/ for(b=0;b<=1;b++) for(c=0;c<=1;c++) for(aa=0;aa<=1;aa++) for(bb=0;bb<=1;bb++) for(cc=0;cc<=1;cc++) if(a+aa!=2&&b+bb!=2&&c+cc!=2&& /*判断逻辑条件*/ a+b+c==1&&aa+bb+cc==1 && (a&&!aa&&b&&!bb||!a&&!b)&& !b &&
(c&&!b&&!bb||(!c&&!cc)&&(b||bb)||!c&cc)) { printf("The man stand on left is a %s.\n", aa?"double--dealer":(a?"honest":"lier")); printf("The man stand on left is a %s.\n", bb?"double--dealer":(b?"honest":"lier")); printf("The man stand on left is a %s.\n", cc?"double--dealer":(c?"honest":"lier")); /*输出最终的推理结果*/ } } *运行结果 The man stand on left is a double--dealer. (左边的人是两面族的) The man stand on center is a lier. (中间的人是说谎族的) The man stand on right is a honest. (右边的人是诚实族的) *思考题 迷语博士遇到三个人,便问第一个人:“你是什么族的?”,回答:“诚实族的。”问第二个人:“你是什么族的?”,答:“说谎族的。”博士又问第二个人:“第一个人真的是诚实族的吗?”,答:“是的。”问第三个人:“你是什么族的?”,答:“诚实族的。”博士又问第三个人:“第一个人是什么族的?”,答:“两面族的。” 请判断这个人到底是哪个民族的? (答案:第一个人是诚实族的,第二个人是两面族的,第三人是说谎族。) |
|
![]() ![]() |