一些好玩的题目

1.

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


题目要求是用编程实现,一开始拿到这个题目,真是两眼一抹黑无从下手的感觉,由实际问题抽象到具体问题对于我这种编程新手来说真的有点困难,于是我参考了别人的答案,才明白了怎么做。
他们将问题转化为逻辑判断,比如a选手说的”b第一,我第二”可以写成((b == 1) + (a == 3) == 1)这样子就满足题目每个选手都说对一半的要求(如果前半句是对的,那么有(b == 1)成立,于是(a == 3)就不成立了,两个逻辑结果相加为1,否则后半句对,(b == 1)不成立,(a == 3)成立,两个逻辑结果依旧相加为1)。同理其他选手也是这样写,最后再套用五重循环遍历所有情况,
当((b == 1) + (a == 3) == 1) &&
((b == 2) + (e == 4) == 1) &&
((c == 1) + (d == 2) == 1) &&
((c == 5) + (d == 3) == 1) &&
((e == 4) + (a == 1) == 1)
满足时候输出结果。
代码如下

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

int main()
{
	int a = 0, b = 0, c = 0, d = 0, e = 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 (((b == 1) + (a == 3) == 1) &&
							((b == 2) + (e == 4) == 1) &&
							((c == 1) + (d == 2) == 1) &&
							((c == 5) + (d == 3) == 1) &&
							((e == 4) + (a == 1) == 1)) {
							//int num = 0;
							//num |= 1 << (a - 1);
							//num |= 1 << (b - 1);
							//num |= 1 << (c - 1);
							//num |= 1 << (d - 1);
							//num |= 1 << (e - 1);
							//while (num) {
							//	if (num % 2 == 0)
							//		break;
							//	else
							//		num = num >> 1;//num /=2;
							//}
							//if (num == 0)
								printf("a=%d,b=%d,c=%d,d=%d,e=%d\n", a, b, c, d, e);
						}//if
					}
				}
			}
		}
	}
	system("pause");
	return 0;
}

代码跑完会输出很多种情况,并列名次是可以的比如11234,12234,但是这种13334显然不符合实际情况,为此我们要保证名次连续(名次可重复如上所说),不妨用二进制的位运算。设置一个num = 0,num的二进制为0000 0000
如果存在第一名就让最后一位为1,即0000 0001
如果存在第二名就让倒数第二为为1,即0000 0010
同理存在第三名即0000 0100等
如果都连续的话,即00001111,0001 1111等说明他们名次连续。

那么如何置1?可以考虑用或运算
例如0000 0000 | 1 = 0000 0001
0000 0000
0000 0001
通过或运算得到0000 0001。
这只是存在第一名的情况,若存在第二名即让倒数第二位为1
0000 0000
0000 0010
通过或运算得到0000 0010。
若存在第三名,就让倒数第三位为1
0000 0000
0000 0100
通过或运算得到0000 0100

可以看出只要将1的二进制数左移再和num进行或运算即可
0000 0001(1的二进制数)
0000 0010(左移1位)
0000 0100(左移1位)
所以若 a = 1的话,num |= 1 << 0
a = 2的话 num |= 1 << 1
a = 3的话 num |= 1 << 2
即num |= 1 << (a - 1)

同理 num |= 1 << (b - 1)
num |= 1 << (c - 1)
num |= 1 << (d - 1)
num |= 1 << (e - 1)
这样得到num序列,比如是上面的13334排名即num = 0000 1101
num % 2得到二进制的最后一位,如果是1说明这个名次存在
num / 2去除当前二进制的最后一位
判断名次的代码如下

while(num) {
	if(num % 2 == 0) { 
		break;
	num = num / 2; //num >> 1
	}
	if(num == 0)
	printf("a=%d b=%d c=%d d=%d e=%d\n", a, b, c, d, e);
}
如果num跑完循环是0的话说明名次是连续的,不然必不连续,比如0000 1101,当遇到倒数第二位的时候为0跳出循环此时num = 0000 11

综上完整正确的代码去掉之前代码的注释就好了。



2.

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。以下为4个嫌疑犯的供词。

A说:不是我。

B说:是C。

C说:是D。

D说:C在胡说

已知3个人说了真话,1个人说的是假话。

现在请根据这些信息,写一个程序来确定到底谁是凶手。



有了第一题的基础,第二题就简单多了,用逻辑判断(四个人所说的话逻辑和==3)即可,代码如下

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

int main()
{
	int killer = 'a';
	for (; killer <= 'd'; killer++) {
		if ((killer != 'a') + (killer == 'c') + (killer == 'd') + (killer != 'd') == 3) {
			printf("killer=%c\n", killer);
		}
	}
	system("pause");
	return 0;
}









  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值