C语言每日一练
2022年1月10日

文章目录

  • 题目描述
  • 问题分析
  • 代码实现
  • 运行结果
  • 后期完善
  • 网上参考

题目描述

有A、B、C、D、E这5个人,每个人额头上都帖了一张黑或白的纸。5人对坐,每个人都可以看到其他人额头上纸的颜色。5人相互观察后:

A说:“我看见有3人额头上贴的是白纸,1人额头上贴的是黑纸。”
B说:“我看见其他4人额头上贴的都是黑纸。”
C说:“我看见1人额头上贴的是白纸,其他3人额头上贴的是黑纸 。”
D说:“我看见4人额头上贴的都是白纸。”
E什么也没说。

现在己知额头上贴黑纸的人说的都是谎话,额头贴白纸的人说的都是实话。问这5人谁的额头上贴的是白纸,谁的额头上贴的是黑纸?

问题分析

个人思路:<仅供参考>
总共5个人,说话的只有4个,简单分析我们可以得知:

4个人说的情况都不相同。A说看到3个人贴白纸,B看到0张白纸,C看到1张白纸,D看到4张白纸,假设他们说的都是真话,那么他们4人所说的话对应的总白纸数依然不同(因为他们自己额头上贴的都是白纸,并不会使其中两人白纸总数相同)。

//4人贴白纸时,总白纸数
#define A_TRUE (3 + 1) //其他3人贴白纸,自己也贴白纸
#define B_TRUE (0 + 1)
#define C_TRUE (1 + 1)
#define D_TRUE (4 + 1)

所以我们可以得出一个隐藏条件——说话的4个人中只有1个人额头上贴白纸,即只有一个人说的是真话。

利用上面这个条件,我们可以通过所有人额头上的总白纸数来判断哪个人说的是真话,例如:B额头贴白纸,他说其他4人贴黑纸,在遍历所有情况时,如果总白纸数为1,且只有B贴白纸时,可能就是正确情况。

为什么说可能呢?由于每个人说的话中没有考虑自己头上的纸张颜色,所以可能会一种矛盾现象:

B额头上贴了白纸,他看到其他4人都贴的是黑纸,C虽然头上贴的的确是黑纸,但他的话是正确的:“我看见1人额头上贴的是白纸,其他3人额头上贴的是黑纸 ”。这就和题目条件冲突了——额头上贴黑纸的人说的都是谎话。

这样一来,在遍历时还需考虑当1个人贴白纸时,其他4个人都不能说真话这一条件,这一点依然可以通过总白纸数来判断。例如:当遍历到B说真话(额头贴白纸)时,判断5个人总白纸数是否等于A,C,D 3个人看到的白纸数(见下面的宏定义),如果有一个相等,说明该遍历结果是错误的。

//4人贴黑纸时,总白纸数(假设它们仍然说真话)
#define A_FALSE (3) //自己贴黑纸,但说的是真话
#define B_FALSE (0)
#define C_FALSE (1)
#define D_FALSE (4)

程序实现上,定义a,b,c,d,e 5个变量,分别表示他们额头上贴的纸张颜色,1表示白色。通过5层for循环,遍历所以可能性,同时满足上面两种情况的,即为正确结果。

【注】我的思路可能推理得太深了,如果觉得处理得太麻烦,可以直接看下文网上参考的思路,该思路逻辑性更强,代码量更少。

代码实现

#include <stdio.h>//4人贴白纸时,总白纸数
#define A_TRUE (3 + 1) //其他3人贴白纸,自己也贴白纸
#define B_TRUE (0 + 1)
#define C_TRUE (1 + 1)
#define D_TRUE (4 + 1)//4人贴黑纸时,总白纸数(假设它们仍然说真话)
#define A_FALSE (3) //自己贴黑纸,但说的是真话
#define B_FALSE (0)
#define C_FALSE (1)
#define D_FALSE (4)int main()
{int A = 0, B = 0, C = 0, D = 0, E = 0;int tmp = 0, flag = 0; //flag = 1表示找到正确结果for(A = 0; A <= 1; A++)for(B = 0; B <= 1; B++)for(C = 0; C <= 1; C++)for(D = 0; D <= 1; D++)for(E = 0; E <= 1; E++){//获取贴白纸的人数tmp = A + B + C + D + E;flag = 0;switch(tmp){//4人只有A贴白纸,且贴黑纸的人说的话不能为真case A_TRUE: if(A && !B && !C && !D &&tmp != B_FALSE &&tmp != C_FALSE &&tmp != D_FALSE)flag = 1;break;//4人只有B贴白纸,且贴黑纸的人说的话不能为真case B_TRUE: if(B && !A && !C && !D &&tmp != A_FALSE &&tmp != C_FALSE &&tmp != D_FALSE)flag = 1;break;//4人只有C贴白纸,且贴黑纸的人说的话不能为真case C_TRUE: if(C && !A && !B && !D &&tmp != A_FALSE &&tmp != B_FALSE &&tmp != D_FALSE)flag = 1;break;//4人只有D贴白纸,且贴黑纸的人说的话不能为真case D_TRUE: if(D && !A && !B && !C &&tmp != A_FALSE &&tmp != B_FALSE &&tmp != C_FALSE)flag = 1;break;}if(flag){printf("A贴%s\n", A ? "白纸" : "黑纸");printf("B贴%s\n", B ? "白纸" : "黑纸");printf("C贴%s\n", C ? "白纸" : "黑纸");printf("D贴%s\n", D ? "白纸" : "黑纸");printf("E贴%s\n", E ? "白纸" : "黑纸");}}return 0;
}

运行结果

后期完善

既然然已经推理出了A、B、C、D 4个人中只有一个人额头贴白纸,这时只需用一个for循环就能遍历出4个人中谁贴了白纸,循环次数为4次(0~3),分别表示A、B、C、D,这样可以减少一些无效的循环次数。

#include <stdio.h>//4人贴白纸时,总白纸数
#define A_TRUE (3 + 1) //其他3人贴白纸,自己也贴白纸
#define B_TRUE (0 + 1)
#define C_TRUE (1 + 1)
#define D_TRUE (4 + 1)//4人贴黑纸时,总白纸数(假设它们仍然说真话)
#define A_FALSE (3) //自己贴黑纸,但说的是真话
#define B_FALSE (0)
#define C_FALSE (1)
#define D_FALSE (4)int main()
{//i表示A,B,C,D 4个人哪个贴白纸,j表示E是否贴白纸int i = 0, j = 0;int tmp = 0, flag = 0; //flag = 1表示找到正确结果for(i = 0; i < 4; i++)for(j = 0; j <= 1; j++){flag = 0;tmp = 1 + j; //总白纸数switch(i){//A说的是真话,其他人说假话?case 0: if(tmp == A_TRUE && tmp != B_FALSE &&tmp != C_FALSE && tmp != D_FALSE)flag = 1; break;//B说的是真话,其他人说假话?case 1: if(tmp == B_TRUE && tmp != A_FALSE &&tmp != C_FALSE && tmp != D_FALSE)flag = 1; break;//C说的是真话,其他人说假话?case 2: if(tmp == C_TRUE && tmp != A_FALSE &&tmp != B_FALSE && tmp != D_FALSE)flag = 1; break;//D说的是真话,其他人说假话?case 3: if(tmp == D_TRUE && tmp != A_FALSE &&tmp != B_FALSE && tmp != C_FALSE)flag = 1; break;}if(flag){printf("A贴%s\n", i == 0 ? "白纸" : "黑纸");printf("B贴%s\n", i == 1 ? "白纸" : "黑纸");printf("C贴%s\n", i == 2 ? "白纸" : "黑纸");printf("D贴%s\n", i == 3 ? "白纸" : "黑纸");printf("E贴%s\n", j == 1 ? "白纸" : "黑纸");}}return 0;
}

网上参考

原文链接:http://c.biancheng.net/cpp/html/3357.html

原文部分思路:


我的思路有一个很大的缺点,那就是花太多心思去推理了(推理过深),好处就是理解起来会好一点。这份代码通过逻辑表达式的方法,一个if语句就得出了结果,优点是逻辑性强,代码量少,不过理解起来可能需要一定的逻辑思维能力

#include<stdio.h>
int main()
{int a, b, c, d, e;  /*0表示黑色,1表示白色*/for(a=0; a<=1; a++)  /*穷举五个人额头帖纸颜色的全部可能*/for(b=0; b<=1; b++)for(c=0; c<=1; c++)for(d=0; d<=1; d++)for(e=0; e<=1; e++)if( (a&&b+c+d+e==3 || !a&&b+c+d+e!=3) &&(b&&a+c+d+e==0 || !b&&a+c+d+e!=0) &&(c&&a+b+d+e==1 || !c&&a+b+d+e!=1) &&(d&&a+b+c+e==4 || !d&&a+b+c+e!=4)){printf("A额头上的贴纸是%s色的.\n",a?"白":"黑");printf("B额头上的贴纸是%s色的.\n",b?"白":"黑");printf("C额头上的贴纸是%s色的.\n",c?"白":"黑");printf("D额头上的贴纸是%s色的.\n",d?"白":"黑");printf("E额头上的贴纸是%s色的.\n",e?"白":"黑");}return 0;
}

C语言每日一练——第74天:黑与白问题相关推荐

  1. 6 获取数组中最小值_C语言每日一练8——数组中最大值和最小值

    题目: 利用指针函数,求某数组中的最大值和最小值. 实现代码: /* ================================================================= ...

  2. C语言每日一练——第85天:三色球问题

    C语言每日一练 2022年3月8日 文章目录 题目描述 问题分析 代码实现 运行结果 网上参考 题目描述 一个口袋中放有12个球,已知其中3个是红的,3个是白的,6个是黑的,现从中任取8个,问共有多少 ...

  3. C语言每日一练——第73天:谁是窃贼问题

    C语言每日一练 202年1月8日 文章目录 题目描述 问题分析 代码实现 运行结果 网上参考 题目描述 警察审问4名窃贼嫌疑犯.现在已知,这4人当中仅有一名是窃贼,还知道这4个人中的每个人要么是诚实的 ...

  4. C语言每日一练——第35天:打印菱形

    C语言每日一练 2021年10月13日 题目描述 输入菱形的高度n(必须为奇数),即正中间星号的个数,打印出用星号组成的菱形 分析 要打印菱形,先要构想要打印的图形样子,就比如下图这种: 我们可以根据 ...

  5. C语言每日一练——第28天:要求输出国际象棋棋盘

    C语言每日一练 2021年10月6日 题目描述 要求输出国际象棋棋盘 分析 先看看国际象棋的棋盘的长相: 可以看出,国际象棋棋盘呈正方形,里面包含8x8总共64个小方格,它们黑白相间.要想在控制台输出 ...

  6. C语言每日一练——第10天:求一个矩阵主对角线及副对角线元素之和

    C语言每日一练 2021年9月18日 题目描述 求一个矩阵主对角线及副对角线元素之和 分析 在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合,矩阵是高等代数学中的常见工具,也常见于 ...

  7. C语言每日一练——第1天:字母大小写转换

    C语言每日一练 2021年9月9日 本人C语言菜鸟,最近工作中频频出现C语言小错误,遂决定使用笨方法提高我的C语言水平,坚持每天一个C语言小练习,养成C语言手感,从此让编程成为习惯. 题目描述 从键盘 ...

  8. 【C语言每日一练——第1练:字母大小写转换】

    C语言每日一练 2022年6月13日 题目描述 从键盘输入一个大写字母,要求改用小写字母输出 分析 从键盘输入可以使用scanf或getchar等函数. 大写字母是一个字符,字符类型数据在C语言中是以 ...

  9. C语言每日一练——第80天:换分币问题

    C语言每日一练 2022年2月13日 文章目录 题目描述 问题分析 代码实现 运行结果 题目描述 将5元的人民币兑换成1元.5角和1角的硬币,共有多少种不同的兑换方法. 问题分析 列举3元1次方程 1 ...

  10. C语言每日一练——第64天:自动发牌程序

    C语言每日一练 2021年12月7日 文章目录 题目描述 问题分析 代码实现 运行结果 网上参考 题目描述 一副扑克有52张牌,打桥牌时应将牌分给4个人.请设计一个程序完成自动发牌的工作.要求:黑桃用 ...

最新文章

  1. 如何打开python的终端窗口_python终端窗口
  2. java excel data 导入数据_java实现导入导出excel数据
  3. 解决ActionBar中不显示item的问题,item显示在overflow中
  4. 2017年我国智能卡行业市场现状及发展趋势分析
  5. java idea 模块_IDEA搭建java多模块module项目-Go语言中文社区
  6. mammary cancer关联规则挖掘详解
  7. Hadoop生态系统的详细介绍
  8. mysqldump备份(全量+增量)
  9. 简洁大气的资源下载站源码emlog模板
  10. [2013.9.10]vb.net坑爹的数组
  11. Microsoft .NET Framework 3.5 SP1 简体中文精简版+.net
  12. Nginx + keepalived 实现高可用
  13. java.lang.NoClassDefFoundError: org/springframework/core/metrics/ApplicationStartup
  14. Linux 入门常见命令大全-初学者必看
  15. 快速排序(java代码)
  16. 局部光照与全局光照的区别
  17. 风云2号卫星云图_今天从零教你开始利用Python打造词云图!
  18. 嵌入式技术学习路线摘要
  19. nlp文本预处理构建词汇表
  20. oracle提取违反,ORA-01002: 提取违反顺序的问题分析

热门文章

  1. Unity 键盘控制摄像机镜头旋转,并限制旋转角度
  2. jUI项目最初的名字为DWZ,这个名字是怎么来的?后来为什么又改为jUI?
  3. 扫描电子显微镜(SEM)低真空技术改造以提升观测能力的解决方案
  4. win7系统提示此windows副本不是正版怎么办?
  5. 学习AngularJs:Directive指令用法
  6. 基于java的springboot宠物商城系统毕业设计springboot开题报告
  7. 正则表达式的基本原理
  8. ZigBee模块无线传输星形拓扑组网结构简介
  9. caputo分数阶导数程序_caputo分数阶导数
  10. PaddleOCR+OpenCV实现中英文识别