偷盗者问题。甲乙丙丁四个嫌疑犯,只有一个是偷盗者。在审讯中,四人都有可能说真话或假话。
甲:乙没偷,丁偷。
乙:我没偷,丙偷。
丙:甲没偷,乙偷。
丁:我没偷。
问谁是小偷。
思路
由于只有一个人是小偷,所以可以枚举四个人分别是小偷,然后再看他们的说法在当前的情况下是否有矛盾。
由于四人都有可能说真话或者假话,所以对他们说的话也要枚举,分别尝试每个人说的是真话或者是假话。
代码
以下代码中a b c d分别代表甲乙丙丁,函数[A/B/C/D][T/F]()即对他们的说法进行判断
#include<stdio.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
int a, b, c, d;
typedef int(*FUNC)();
#define JF(X) int X##F(){return !X##T();}
int AT(){ return b == 0 && d == 1; }
int BT(){ return b == 0 && c == 1; }
int CT(){ return a == 0 && b == 1; }
int DT(){ return d == 0; }
JF(A)
JF(B)
JF(C)
JF(D)
int main()
{
for (int i = 1; i <= 4; ++i)
{
a = i == 1 ? 1 : 0;
b = i == 2 ? 1 : 0;
c = i == 3 ? 1 : 0;
d = i == 4 ? 1 : 0;
FUNC f1[] = { AF, AT };
FUNC f2[] = { BF, BT };
FUNC f3[] = { CF, CT };
FUNC f4[] = { DF, DT };
FOR(d1, 0, 1)
FOR(d2, 0, 1)
FOR(d3, 0, 1)
FOR(d4, 0, 1)
{
if (f1[d1]() && f2[d2]() && f3[d3]() && f4[d4]())
{
printf("小偷:%c\n",'a' + i - 1);
printf("真话or假话:\n");
printf("a b c d\n");
printf("%d %d %d %d\n", d1, d2, d3, d4);
puts("-----------");
}
}
}
}
运行结果:

可以发现,其实甲乙丙丁都有可能是小偷。
通过逻辑推理和编码验证,解析甲乙丙丁四人陈述中的真实小偷身份,展示了一种枚举和验证真伪的算法解决方案。

778

被折叠的 条评论
为什么被折叠?



