关于《高质量》第三版第4.13节例4的更正!

 一个名叫cao_julians的网友对《高质量》第三版第4.13节例4的实现提出了质疑,我认真核对后也觉得欠妥。问题主要是对TRUE的定义和理解。现在更新如下:

       例4:协助破案。假设已经查清,有A、B、C、D、E五个嫌疑人可能参与制造了一起银行抢劫案,但是不知道其中到底哪几个人是真正的案犯。不过,有确凿证据表明:
    ① 如果A参与了作案,则B一定也会参与。
    ② B和C两人中只有一人参与了作案。
    ③ C和D要么都参与了作案,要么都没有参与。
    ④ D和E两个人中至少有一人参与作案。
    ⑤ 如果E作案,则A和D一定参与作案。
是不是有点绕口?我们可以用数理逻辑中的正规表达式来表示上述论断:
    ①   A→B
    ② (B∧ C)∨( B∧C)
    ③ (C∧D)∨( C∧ D)
    ④ (D∨E)
    ⑤   E→(A∧D)
我们现在用1(可理解为TRUE)表示作案,0(可理解为FALSE)表示未作案,则每个人的取值范围就是{0,1}。然后我们在5个人取值的所有可能的组合空间中进行搜索,如果某个组合同时满足这5条线索,那么它就是本案的答案了。于是,上述正规表达式可以进一步表示为下列C++/C逻辑表达式:
    ① A == 0 ||(A == 1 && B == 1)
    ② B + C == 1
    ③ C == D
    ④ D + E >= 1
    ⑤ E == 0 ||(E == 1 && A == 1 && D == 1)
我们用另一个变量count来表示组合空间中某一个组合能够满足几条论断,如果出现了这样一个组合:它同时满足了这5条论断,那么它就是我们要找的组合。

程序见示例4-21。
                                                      示例4-21


#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;   // 计数器清0
                                      count += ( A == 0 || ( A == 1 && B == 1 ) ) ? 1 : 0;
                                      count += ( ( B + C ) == 1 ) ? 1 : 0;
                                      count += ( C == D ) ? 1 : 0;
                                      count += ( ( D + E ) >= 1 ) ? 1 : 0;
                                      count += ( E == 0 ||
                                                 ( E == 1 && A == 1 && D == 1 ) ) ? 1 : 0;
                                      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");
    return 0;
}



输出结果如下:
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.

上述方法有些舍近求远。实际上,这个问题的更好的解决办法是直接使用所有逻辑表达式的“与”的结果来判断,即定义count为逻辑变量并修改为hasFound,此法更直接了当。实现如下:

首先把逻辑表达式改为:
    ① !A || (A && B)
    ② (B && !C) || (!B && C)
    ③ (C && D) || (!C && !D)
    ④  D || E
    ⑤ !E || (E && A && D)

代码就可以如下修改为:



#include <stdio.h>
int main(void)
{
    int A, B, C, D, E;
    bool hasFound = false;
    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++) {
                        hasFound = true;
                        hasFound = hasFound && (!A || (A && B));
                        hasFound = hasFound && ((B && !C) || (!B && C));
                        hasFound = hasFound && ((C && D) || (!C && !D));
                        hasFound = hasFound && (D || E);
                        hasFound = hasFound && (!E || (E && A && D));
                        if (hasFound)  // 找到一个满足所有条件的组合
                            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");
    return 0;
}


输出结果如下:
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.

感谢网友cao_julians的热心和支持!谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值