前幾天,鵬哥在作業中給出了這樣一道題:
5位運動員參加了10米臺跳水比賽,有人讓他們預測比賽結果
A選手說:B第一,我第三。
B選手說:我第二,E第四。
C選手說:我第一,D第二。
D選手說:C最後,我第三。
E選手說:我第四,A第一。
比賽結束後,每位選手都說對了一半,請編程確定比賽的名次。
這道題相信很多人都知道,程序寫起來也不是特別難,其主要的源程序如下:
#include<stdio.h>
int main()
{
int a , b , c , d , e;
int ret = 0;
for (a = 1; a < 6; a++)
{
for (b = 1; b < 6; b++)
{
for (c = 1; c < 6; c++)
{
for (d = 1; d < 6; d++)
{
for (e = 1; e < 6; e++)
{
if ((b == 1) + (a == 3) == 1 &&
(b == 2) + (e == 4) == 1 &&
(c == 1) + (d == 2) == 1 &&
(c == 5) + (d == 3) == 1 &&
(e == 4) + (a == 1) == 1)
{
printf("a=%d,b=%d,c=%d,d=%d,e=%d\n", a, b, c, d, e);
}
}
}
}
}
}
system("pause");
return 0;
}
我自己當時也是寫到這裏的,本以爲就行了,可是輸出的結果並不是所期望的:
如圖所示,這和我們所想的並不一樣,照理來說應該只有第一種一個答案纔對,而它將一些名次不連續的組也輸出來了,有人覺得那隻輸出第一行不就行了,可這只是一種取巧的方法,這道題只是它的答案恰好在第一行,那如果它在第二行或第三行以及其他行數呢?所以,這個程序還是要繼續改進的,這裏我和大家分享下學習到的方法:
首先我們目的是想讓其按連續的順序輸出來,中間不要空出數字,那我們可以將它放入一個二進制位中,如果它存入的值是連續的1,那就說明這個次序是連續的。
比如給定義一個 int ret=0,由於只有5個名次,所以這裏ret只看它後八位,剛開始ret應該是0000 0000,如果是1的話,可直接讓它和ret相或,其結果是1,如果是2的話就讓1左移一位再和ret相或,如果是3就把1左移兩位再相或,以此類推,如果是n的話,就讓1左移(n-1)位和ret相或,這樣就能確保它的名次是連續的了,具體的代碼如下:
ret = ret | 1 << (a - 1);
ret = ret | 1 << (b - 1);
ret = ret | 1 << (c - 1);
ret = ret | 1 << (d - 1);
ret = ret | 1 << (e - 1);
這是我們將所有的名次存入ret中
下一步我們就該判斷ret的二進制是否爲連續的1,那我們可以用while循環和if語句來實現,代碼如下:
while (ret)
{
if (ret % 2 == 0)
break;
else ret = ret / 2;
}
如果while循環整個執行完畢,那說明我們的ret此時爲0,並且名次是按連續的順序輸出的;如果從break跳出循環的話,那此時ret就不等於0,也說明名次並不是按順序輸出的。因此整個程序的代碼應該是這樣的:
#include<stdio.h>
int main()
{
int a , b , c , d , e;
int ret = 0;
for (a = 1; a < 6; a++)
{
for (b = 1; b < 6; b++)
{
for (c = 1; c < 6; c++)
{
for (d = 1; d < 6; d++)
{
for (e = 1; e < 6; e++)
{
if ((b == 1) + (a == 3) == 1 &&
(b == 2) + (e == 4) == 1 &&
(c == 1) + (d == 2) == 1 &&
(c == 5) + (d == 3) == 1 &&
(e == 4) + (a == 1) == 1)
{
ret = 0;
ret = ret | 1 << (a - 1);
ret = ret | 1 << (b - 1);
ret = ret | 1 << (c - 1);
ret = ret | 1 << (d - 1);
ret = ret | 1 << (e - 1);
while (ret)
{
if (ret % 2 == 0)
break;
else ret = ret / 2;
}
if (ret == 0)
printf("a=%d,b=%d,c=%d,d=%d,e=%d\n", a, b, c, d, e);
}
}
}
}
}
}
system("pause");
return 0;
}
其運行結果如下:
在這裏要注意下每次給每個名次組存放的時候,要把ret初始化,這樣就不會將上次的值再傳遞到這次。
整個過程和流程就是這樣,當然我這也不是最簡單,最好的方法,肯定還有大神有其他好的方法,如果有的話,可以在留言中分享,謝謝