1. 程式人生 > >邏輯推理典例:根據資訊排名次

邏輯推理典例:根據資訊排名次

邏輯推理在生活中處處可見,它有助於我們鍛鍊自己的思維

這裡有這樣一道很經典的邏輯推理題,看似簡單裡面卻暗藏很多陷阱,往往大多數人都得到的是不完全正確的答案;


讓我們來分析一下這道典例

5位運動員參加了10米臺跳水比賽,有人讓他們預測比賽結果
A選手說:B第二,我第三;
B選手說:我第二,E第四;
C選手說:我第一,D第二;
D選手說:C最後,我第三;
E選手說:我第四,A第一;
比賽結束後,每位選手都說對了一半,請程式設計確定比賽的名次

解題思路:

1.看到這種題,我們首先需要把所有結果都陳列出來,然後對每一次結果進行判斷,然後對不符合條件的排名情況捨棄,最終就能得到我們的正確名次;

 

2.對於每位選手只說對了一半我們該如何來判斷呢?

例如對於A選手,我們如何判斷他說對了一半?
有人會立馬想到:if ( b == 2 || a== 3)
這無疑是有漏洞的:b==2和a==3都成立這條件也為真,然而題目只需要有且只能說對一半;

然後會有人想到:if ( (b == 2 || a== 3) == 1  && (b == 2 && a== 3)==0 )
對,這能滿足題目的需求,達到只能說對一半的要求,但這樣寫是否過於複雜了?
下面介紹一種最優的解法:
if((b == 2) + (a == 3) == 1);

 

3.在做這道題時,我們得先了解一個常識,這也是本題的關鍵和陷阱所在。在排名中我們來列舉如下情況:

 1.  a、b、c、d、e的名次為  1,2,3,4,5;
 2.  a、b、c、d、e的名次為  1,1,3,4,5;
 3.  a、b、c、d、e的名次為  1,1,2,3,2;
 4.  a、b、c、d、e的名次為  1,3,3,4,5;
其中哪些排名是不可能的呢?
2和4的排名是不可能出現的。生活實際中,排名是可以重疊的(兩個或多個並列一個名次),但不能跨級,意思是,有第一名,沒第二名,卻有第三名,這樣的情況你在生活實際中遇到過嗎?肯定是不可能的


所以,我們在判斷排名是否合格時要排除跨級的這種情況。
那麼難點來了,如何判斷這五個人的排名是否跨級了
解法:我們將這五個人的名次都放到 flag 變數(初始化為零)的位元位中,如果出現第一名,就讓第一個位元位(從右往左)置一,如果出現了第二名,就讓第二個位元位置一,.......    然後我們來判斷flag從右往左如果位元位之間有零,則不符合要求(即位元位從右往左不能出現1 0 1 這種序列

下面呈上原始碼:

#include<stdio.h>
/*5位運動員參加了10米臺跳水比賽,有人讓他們預測比賽結果
A選手說:B第二,我第三;
B選手說:我第二,E第四;
C選手說:我第一,D第二;
D選手說:C最後,我第三;
E選手說:我第四,A第一;
比賽結束後,每位選手都說對了一半,請程式設計確定比賽的名次。 */

//注意:續航符打出後需直接回車,然後再寫程式碼,回車前回車會不能有空格,否則就會有警告
//注意:續航符後面不能加註釋,否則直接報錯 
int main()
{
	int a,b,c,d,e;
	int flag = 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++)
					{
						flag = 0;
						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)
							{
								flag |= 1 << (a-1);
								flag |= 1 << (b-1);
								flag |= 1 << (c-1);
								flag |= 1 << (d-1);
								flag |= 1 << (e-1);
								while (flag)
								{
									if (!(flag&1))
									break;
									flag >>= 1;
								}
								if (flag == 0)
								{
									printf("a:%d  b:%d  c:%d  d:%d  e:%d\n", a, b, c, d, e);
								}
							}
					} 
	return 0;
}

我在寫這段程式碼時用到了續航符 \ ,然後總是有警告和錯誤,經百度後總結如下:
續航符後面不能有註釋,否則會報錯;
續航符打出後需直接回車,然後再寫程式碼,回車前回車會不能有空格,否則就會有警告;