C语言编程解趣题系列——找凶手和比赛名次

Posted 未见花闻

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言编程解趣题系列——找凶手和比赛名次相关的知识,希望对你有一定的参考价值。

⭐️前面的话⭐️

嗨喽!我要来水文章咯!上一篇文章介绍了C语言库中一些关于字符的函数和深入了解了指针,相信大家都看累了,这篇文章博主将分享两个有趣的问题找凶手和比赛名次,让学习C语言不枯燥。

📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
✉️坚持和努力一定能换来诗与远方!
🙏作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
博主的码云gitee,平常博主写的程序代码都在里面。


🔐问题1:找凶手

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。
以下为4个嫌疑犯的供词:
A说:不是我。
B说:是C。
C说:是D。
D说:C在胡说。
已知3个人说了真话,1个人说的是假话。
现在请根据这些信息,写一个程序来确定到底谁是凶手。

💡解题思路

首先根据我们人类的思维可以确定一共有4种情况将这些情况列成一个表(其中1代表真,0代表假):

ABCD推断
0111C,D矛盾
1011C,D矛盾
1101C是凶手
1110B,C矛盾

根据推理:
B,C中必有一个说谎;
C,D中必有一个说谎;
A,D说的一定是真话。
所以推断出C是凶手。

人类可以通过像这样的推理得到谁是凶手,但是计算机不行,它没有人类的思维,所以想要使用编程解决这道题,必须从计算机的角度出发,以计算机的思维解决。
通过题目可知四句话三真一假,所以我们可以通过设立四个判断语句,满足四个判断语句结果之和为3,这就模拟了三真一假。
对于判断语句,A,B,C,D四个人的话翻译一下可以得到:
A:murderer != 'A'
B:murderer == 'C'
C:murderer == 'D'
D:murderer != 'D'
我们可以假设一个凶手,比如从A开始,然后进行四个条件判断并将其结果加起来,如果满足判断结果之和为3,则A就是凶手。

🔑编程代码与运行结果
编程代码:

#include <stdio.h>
int main()
{
	int i = 0;
	char murderer = 'A';
	for (i = 0; i < 4; i++)
	{
		murderer = 'A' + i;//假设凶手是A
		int sum = 0;
		sum = (murderer != 'A') + (murderer == 'C') + (murderer == 'D') + (murderer != 'D');//它们四个人三个人说了真话
		if (sum == 3)
		{
			printf("%c是凶手。\\n", murderer);//C是凶手
			break;
		}
	}
	return 0;
}

运行结果:

C是凶手。

D:\\gtee\\C-learning-code-and-project\\猜凶手\\Debug\\猜凶手.exe (进程 29596)已退出,代码为 0。
按任意键关闭此窗口. . .

与我们想的一致,完成!

🔐问题2:比赛名次

5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。

💡解题思路

用计算机的思维,首先将5位运动员讲的话以说对一半的形式翻译成5个判断语句,这里所谓的“说对一半”,就是5位运动员中一句话为真,一句话为假。翻译成判断语句如下:
A = (((b == 2) && (a == 3)) == 0) && (((b == 2) || (a == 3)) == 1);
B = (((b == 2) && (e == 4)) == 0) && (((b == 2) || (e == 4)) == 1);
C = (((c == 1) && (d == 2)) == 0) && (((c == 1) || (d == 2)) == 1);
D = (((c == 5) && (d == 3)) == 0) && (((c == 5) || (d == 3)) == 1);
E = (((e == 4) && (a == 1)) == 0) && (((e == 4) || (a == 1)) == 1);
满足A+B+C+D+E==5A*B*C*D*E=1就能模拟5位运动员说的话了。

A = (b == 2) + (a == 3);
B = (b == 2) + (e == 4);
C = (c == 1) + (d == 2);
D = (c == 5) + (d == 3);
E = (e == 4) + (a == 1);
满足A*B*C*D*E=1就能模拟5位运动员说的话了。
然后就是将所有的可能情况列出来,去通过这5个判断,如果满足A*B*C*D*E=1就能得到比赛的名次。
对于怎么得出所有的比赛名次情况,有两种方法:
方法1:使用5个嵌套的循环将所有1 2 3 4 5名次组合数得出来,但是名次是不能出现重复的,那我们就将得到的组合数全部乘起来,如果结果等于1*2*3*4*5=120,就满足得到的组合数每个都不相同,这样名次就不会重复了。
方法2:使用随机数,得到5个范围为1~5的数,同理为了避免名次重复,通过判断5个数的乘积结果是否为120,来筛选没有重复数字的组合。
🔑编程代码与运行结果
方法1编程代码:

#include <stdio.h>

int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	int d = 0;
	int e = 0;
	int A = 0;
	int B = 0;
	int C = 0;
	int D = 0;
	int E = 0;
	int test = 0;

	for (a = 1; a <= 5; a++)
	{
		for (b = 1; b <= 5; b++)
		{
			for (c = 1; c <= 5; c++)
			{
				for (d = 1; d <= 5; d++)
				{
					for (e = 1; e <= 5; e++)
					{
						if (a * b * c * d * e == 120)//生成五位选手所有排名可能
						{
							A = (((b == 2) && (a == 3)) == 0) && (((b == 2) || (a == 3)) == 1);
							B = (((b == 2) && (e == 4)) == 0) && (((b == 2) || (e == 4)) == 1);
							C = (((c == 1) && (d == 2)) == 0) && (((c == 1) || (d == 2)) == 1);
							D = (((c == 5) && (d == 3)) == 0) && (((c == 5) || (d == 3)) == 1);
							E = (((e == 4) && (a == 1)) == 0) && (((e == 4) || (a == 1)) == 1);
							//A = (b == 2) + (a == 3);
							//B = (b == 2) + (e == 4);
							//C = (c == 1) + (d == 2);
							//D = (c == 5) + (d == 3);
							//E = (e == 4) + (a == 1);
							//test = A + B + C + D + E;//满足五位选手说的话半句真半句假,后面判断条件要要改为test == 5;
							test = A * B * C * D * E;//满足五位选手说的话为半真
							if (a * b * c * d * e == 120)
							{
								if (test == 1)
								{
									printf("A->%d B->%d C->%d D->%d E->%d\\n", a, b, c, d, e);
									break;
								}
							}
						}
					}
				}
			}
		}
	}
	return 0;
}

方法1运行结果:

A->3 B->1 C->5 D->2 E->4

D:\\gtee\\C-learning-code-and-project\\test_809\\Debug\\test_809.exe (进程 20136)已退出,代码为 0。
按任意键关闭此窗口. . .

方法2编程代码:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	int d = 0;
	int e = 0;
	int A = 0;
	int B = 0;
	int C = 0;
	int D = 0;
	int E = 0;
	int test = 0;
	srand((unsigned int)time(NULL));
	while(1)
	{
		a = rand() % 5 + 1;
		b = rand() % 5 + 1;
		c = rand() % 5 + 1;
		d = rand() % 5 + 1;
		e = rand() % 5 + 1;//利用随机数生成五位选手排名可能情况
		
		if (a * b * c * d * e == 120)
		{
			//A = (((b == 2) && (a == 3)) == 0) && (((b == 2) || (a == 3)) == 1);
			//B = (((b == 2) && (e == 4)) == 0) && (((b == 2) || (e == 4)) == 1);
			//C = (((c == 1) && (d == 2)) == 0) && (((c == 1) || (d == 2)) == 1);
			//D = (((c == 5) && (d == 3)) == 0) && (((c == 5) || (d == 3)) == 1);
			//E = (((e == 4) && (a == 1)) == 0) && (((e == 4) || (a == 1)) == 1);
			A = (b == 2) + (a == 3);
			B = (b == 2) + (e == 4);
			C = (c == 1) + (d == 2);
			D = (c == 5) + (d == 3);
			E = (e == 4) + (a == 1);
			test = A * B * C * D * E;//满足五位选手说的话为半真
			if (test == 1)
			{
				printf("A->%d B->%d C->%d D->%d E->%d\\n", a, b, c, d, e);//如果得出排名打印并退出循环
				break;
			}
		}
	}
	return 0;
}

方法2运行结果:

A->3 B->1 C->5 D->2 E->4

D:\\gtee\\C-learning-code-and-project\\test_809\\Debug\\test_809.exe (进程 31128)已退出,代码为 0。
按任意键关闭此窗口. . .

两种方法结果一致,都得到了五位比赛选手的排名。

觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!

以上是关于C语言编程解趣题系列——找凶手和比赛名次的主要内容,如果未能解决你的问题,请参考以下文章

确定比赛名次 UDU-1285 + 逃生 UDU 4857 拓扑排序(找不同)

UVA12034比赛名次

拓扑排序--确定比赛名次(模板题)

典型的三道编程练习题

请高手帮忙,要解题思路或者是代码,最好c语言。

拓扑排序_确定比赛名次