枚举法用于逻辑问题的处理
前言
遇到一些邏輯問題的時候,因為數據量不大的關系,我們通常只是需要人工枚舉出所有的情況就可以。今天發現了怎么用計算機去枚舉,況且記錄一波。
邏輯枚舉
問題 1:
警察局抓了a,b,c,d四名偷竊嫌疑犯,其中有一人是小偷。審問中:
a說:“我不是小偷”。
b說:“c是小偷”。
c說:“小偷肯定是d”。
d說:“c冤枉人”。
現在已經知道四人中三人說的是真話,一人說的是假話。問到底誰是小偷?
分析
問題只有4中情況,而且他們4個人說的話只有4句為真。假設小偷為x,他們四個人說的話可以轉換為以下四條邏輯表達式:
- a的話:x !=a
- b的話:x = c
- c的話:x = d
- d的話:x != d
接下來就只需要枚舉x可取的四個值,滿足上面三條邏輯表達式有三條為真的情況就得到了正解
代碼如下
#include <iostream> #include <cstdio> using namespace std; int main() {int x;for (x = 'a'; x <= 'd'; x++)if (((x != 'a') + (x == 'c') + (x == 'd') + (x !=' d')) == 3)printf("%c",x);return 0; }問題 2:
3位老師對某次數學競賽進行預測,他們的預測為:
甲說: 學生A得第一名,學生B得第三名
乙說:學生C得第一名,學生D得第四名
丙說:學生D得第二名,學生A得第三名。
競賽結果表明,他們都說對一半,說錯一半,且無并列名次,試編寫程序a,b,c,d各自的名稱。
分析
如果不除去并列名次,則有444^444種情況,人工枚舉會稍顯麻煩。我們還是可以按照上一題的思想進行枚舉。
假設a,b,c,d分別表示學生A,學生B,學生C和學生D所獲得的名次,那么三位教練說的話可以可以用如下邏輯表達式表示:
- 甲說的話:a = 1 , b = 3
- 乙說的話:c = 1 , d = 4
- 丙說的話:d = 2 , a = 3
由于他們說的話都只有一半是對的,所以我們可以得到以下條件句:
- (a=1) + (b=3) = 1
- (c=1) + (d=4) = 1
- (d=2) + (a=3) = 1
代碼如下
#include <iostream> #include <cstdio> using namespace std; int main() {int a,b,c,d;for(a=1;a<=4;a++){for(b=1;b<=4;b++)if(a!=b){//去除重復名次for(c=1;c<=4;c++)if(a!=c&&b!=c){d=10-a-b-c; //根據a,b,c的名次計算d的名次if(a!=d&&b!=d&&c!=d){if((a==1)+(b==3)==1&&(c==1)+(d==4)==1&&(d==2)+(a==3)==1)printf("a=%d, b=%d, c=%d, d=%d",a,b,c,d);}}}}return 0; }實戰演練
問題描述
公安人員審問甲、乙、丙、丁四個嫌疑犯,已確知,這四個人當中僅有一人是偷竊者,還知道這四個人的答話,要么完全誠實,要么完全說謊。在回答公安人員的問話中:
甲說:“乙沒有偷,是丁偷的。”
乙說:“我沒有偷,是丙偷的。”
丙說:“甲沒有偷,是乙偷的。”
丁說:“我沒有偷,我用的那東西是我家里的。”
請根據上述四人答話,判斷誰是偷竊者。
輸入格式
無
輸出格式
輸出一個字符,表示偷竊者是誰,A表示甲,B表示乙,C表示丙,D表示丁。
分析
- 這對絕大多數人來說,都只是一道水題。雖然情況不少,我們只要通過人工的邏輯推理很快可以得到正確的答案。
- 下面我們繼續用上面講解到的思路進行求解,我們假設兇手為x,可以得到他們說的話對應的邏輯表示式:
- 甲說的話表示x != B , x = D
- 乙說的話表示x != B , x = C
- 丙說的話表示x != A , x = B
- 丁說的話表示x != D
- 因為甲乙丙說的話都包含兩個部分,而且他們說的話要么全為真,要么全為假。(至于丁說的話對結果有沒有影響,我還有點疑問)就可得以下條件句:
- (x!=‘B’)+(x=‘D’)!=1
- (x!=‘B’)+(x=‘C’)!=1
- (x!=‘A’)+(x=‘B’)!=1
代碼如下
#include <iostream> #include <cstdio>#define x1 (x!='B')+(x=='D') #define x2 (x!='B')+(x=='C') #define x3 (x!='A')+(x=='B')using namespace std;int main() {int x;for(x='A';x<='D';x++)if((x1!=1)&&(x2!=1)&&(x3!=1))printf("%c",x);return 0; }總結
以上是生活随笔為你收集整理的枚举法用于逻辑问题的处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++描述的位运算总结
- 下一篇: P1464 Function(递归式的记