问题 1 描述:
日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。以下为4个嫌疑犯的供词:
A说:不是我。
B说:是C。
C说:是D。
D说:C在胡说
已知3个人说了真话,1个人说的是假话。现在请根据这些信息,写一个程序来确定到底谁是凶手
思路: 将嫌疑人A B C D放进数组中 killer[4] 中并初始化为{0,0,0,0},0 代表不是凶手,若值为 1 代表是凶手。
其中 3 个人说的是真话,即按照四个人的描述进行判断,是真话为 1 假话为 0,则和为3;
遍历四个人。
实现代码:使用 C语言进行代码实现
/*谁是凶手*/
#include <stdio.h>
#include <stdlib.h>
int main() {
int killer[4] = { 0 };
int i = 0;
for (i = 0; i < 4; i++) {
killer[i] = 1;
if ((killer[0] != 1) + (killer[2] == 1) + (killer[3] == 1) + (killer[3] != 1) == 3) {
printf("凶手是%c \n", i + 'A');
}
killer[i] = 0; // 若 i 不是凶手, 将它值零
}
system("pause");
return 0;
}
运行结果:
凶手是C
请按任意键继续. . .
关键问题在于将四个人的描述转换成判断语句进行运算。然后遍历每种可能性,满足所描述内容条件的即为凶手。
问题 2 描述:
5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请确定比赛的名次。
思路: 如同问题1 ,将选手所描述的内容转换成判断语句进行计算,例如A选手所说:(B == 2)+ (A == 3)由于每位选手都说对一般,所以A选手所淑的内容可以转换成 (B == 2)+ (A == 3) == 1;将每位选手的描述都转换位判断语句。
然后,采用暴力遍历的方法判断每一种排名情况,哪种情况四位选手所描述的内容,即为比赛的名次。
注意,由于暴力遍历时可能出现多次遍历同一个选手情况,所以使用有一个函数,这个函数是用来确保每位都参加了比赛
代码实现:
#include <stdio.h>
#include <stdlib.h>
int isDiff(int a, int b, int c, int d, int e) { // 使用位运算确保每人进行一次比赛
int temp = 0;
temp |= 1 << (a - 1); //移动 a - 1 位使其为1
temp |= 1 << (b - 1);
temp |= 1 << (c - 1);
temp |= 1 << (d - 1);
temp |= 1 << (e - 1);
if (temp == 31) { // 即二进制 0001 1111 == 31
return 1;
}
return 0;
}
int main() {
int a, b, c, d, 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 == 2) + (a == 3) == 1 &&
(b == 2) + (e == 4) == 1 &&
(c == 1) + (d == 2) == 1 &&
(c == 5) + (d == 3) == 1 &&
(e == 4) + (a == 1) == 1 &&
isDiff(a, b, c, d, e))
printf(" a :%d\n b :%d\n c : %d\n d : %d\n e : %d\n", a, b, c, d, e);
}
}
}
}
}
system("pause");
return 0;
}
运行结果:
a :3
b :1
c : 5
d : 2
e : 4
请按任意键继续. . .
代码中 isDiff 函数采用位运算的形式进行判断。