C++案例——协助破案

题目

协助破案。假设已经查清,有 A、B、C、D、E 五个嫌疑人可能参与制造了一起抢劫银行案,但不知道其中哪几个是真正的案犯。不过,有确凿证据表明:

  1. 如果 A 参与了作案,则 B 一定也会参与。
  2. B 和 C 两人中只有一人参与了作案。
  3. C 和 D 要么都参与了作案,要么都没有参与。
  4. D 和 E 两个人中至少有一人参与作案。
  5. 如果 E 作案,则 A 和 D 一定参与作案。

分析

正规表达式

上述论断可以用数理逻辑中的正规表达式来表示:

  1. \(A \to B\)
  2. \(\left( {B \wedge \neg C} \right) \vee \left( {\neg B \wedge C} \right)\)
  3. \(\left( {C \wedge D} \right) \vee \left( {\neg C \wedge \neg D} \right)\)
  4. \(\left( {D \wedge E} \right) \vee \left( {\neg D \wedge E} \right) \vee \left( {D \wedge \neg E} \right)\)
  5. \(E \to \left( {A \wedge D} \right)\)

现在假设用 1(TRUE)表示作案,0(FALSE)表示未作案,则每个人的取值范围就是 \(\{0,1\}\) 。然后我们在 5 个人取值的所有可能的组合空间中进行搜索,同时满足这五条线索的一个组合就是本案的答案了。

C++ / C 逻辑表达式

于是上述正规表达式可以进一步表示为下列 C++ / C 逻辑表达式:

  1. A==0 || (A==1 && B==1) 
    
  2. B+C == 1
    
  3. C == D
    
  4. D+E >= 1
    
  5. E==0 || (E==1 && A==1 && D==1)
    

我们用另一个变量 count 来表示组合空间中某一个组合能够满足几条论断,如果出现了这样一个组合:它同时满足了这五条论断,那么它就是我们要找的组合。

实现

#include<stdio.h>
int main(void)
{
    int A,B,C,D,E;
    int count = 0;
    for (A = 0; A < 2; A++)
    {
        for (B = 0; B < 2; B++)
        {
            for (C = 0; C < 2; C++)
            {
                for (D = 0; D < 2; D++)
                {
                    for (E = 0; E < 2; E++)
                    {
                        count = 0; // 计数器清零
                        count += (A==0 || (A==1 && B==1));
                        count += (B+C == 1);
                        count += (C == D);
                        count += (D+E >= 1);
                        count += (E==0 || (E==1 && A==1 && D==1));
                        if (count == 5) // 找到一个满足所有条件的组合
                        {
                            goto finish;
                        }
                    }
                }
            }
        }
    }
    finish:
    printf("Suspect A is %s.\n", (A==1)?"a criminal":"not a criminal");
    printf("Suspect B is %s.\n", (B==1)?"a criminal":"not a criminal");
    printf("Suspect C is %s.\n", (C==1)?"a criminal":"not a criminal");
    printf("Suspect D is %s.\n", (D==1)?"a criminal":"not a criminal");
    printf("Suspect E is %s.\n", (E==1)?"a criminal":"not a criminal");
}

输出结果如下:

Suspect A is not a criminal.
Suspect B is not a criminal.
Suspect C is a criminal.
Suspect D is a criminal.
Suspect E is not a criminal.

摘自《高质量程序设计指南——C++/C语言 第3版》 P82

posted @ 2022-06-12 17:58  GShang  阅读(136)  评论(0编辑  收藏  举报