八皇后問題求解 之遞迴

2021-07-22 17:25:49 字數 4149 閱讀 2406

什麼是八皇后問題?

該問題是國際西洋棋棋手馬克斯·貝瑟爾於2023年提出:在8×8格的西洋棋上擺放八個皇后,使其不能互相攻擊。

所以,我們要了解皇后的攻擊模式:皇后可以橫著走任意步數、豎著走任意步數、斜著走任意步數。

翻譯過來就是:即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。(實際上,總共有 92種擺法 )

例如,下面的這種擺法(0表示沒有皇后,1表示擺放了皇后):10

0000

0000

1000

0000

0010

0000

0000

1000

0100

0001

0000

0000

0001

0000

0000

01問題1:八皇后的儲存問題

八皇后為8*8的格式,為了節約記憶體,我們可以將棋盤定義為unsigned char chess[8](當然char chess[8]也沒問題)

為什麼呢?char型別為8bit,所以總共就有8*8bit,其中,我們讓有皇后的位置標記為1,讓沒有皇后的位置標記為0

問題2:八皇后的列印

我們把八皇后的列印單獨寫乙個函式,模組化方便定位錯誤。

int count=0;//累積八皇后的方案個數,是乙個全域性變數

void eight_queen_print(unsigned

char *chess)

putchar('\n');

}putchar('\n');

}

列印出來的格式可能是:

no.92

1 0 0 0 0 0 0 0

0 0 0 0 1 0 0 0

0 0 0 0 0 0 0 1

0 0 0 0 0 1 0 0

0 0 1 0 0 0 0 0

0 0 0 0 0 0 1 0

0 1 0 0 0 0 0 0

0 0 0 1 0 0 0 0

問題3:八皇后的和平相處(如何判斷該位置是否可以放置乙個皇后)

1.首先,我們把有皇后的位置標記為1,把沒有皇后的位置標記為0

2.其次,我們寫乙個函式單獨檢測該位置是否可以放置皇后:

—— a.檢測橫向時候是否已存在乙個皇后

—— b.檢測豎向是否已經存在乙個皇后(由於我們排列皇后的順序為從上到下,所以我們可以只檢測該行上面的幾個行上是否有皇后即可)

—— c.檢測斜線方向(此時的斜線除了從左上角到右下角之外,還有從右上角到左下角;同上所述,我們只要檢測該行上面幾個行的斜線方向即可)

//這裡用到了位運算,因為與八皇后問題無關,不做過多的解釋了

//如果該位置可以放置皇后,返回0,否則返回1

//傳入棋盤當前的狀態:chess

//傳入想要檢測的位置:行數和列數

int eight_queen_safe(unsigned

char *chess,int row,int col)

//檢測豎向:我們只需要檢測row個行數就像了,比如傳入的row為3,那麼此時我麼就只要檢測下標為0,1,2的行數即可

for(int i=0;iif(chess[i] & (1

<<(7 & ~col)))return -1;

}//左上角到右下角的方向

for(int i=row-1,j=col-1;i >= 0 && j >= 0;--i,--j)

//右上角到左下角的方向

for(int i=row-1,j=col+1;i>=0 && j<=7;--i,++j)

return

0;}

問題4:如何遞迴

1.首先,只要進入8皇后的遞迴函式,就表明該函式沒有到結束條件,我們直接設定和檢測皇后的位置(注意此時我們就要像遞迴函式傳入:棋盤狀態,行數和列數),我們從指定的行數和列數開始向後檢測。並設定位置。當我們發現某個位置可行的時候,我們就開啟遞迴,因為我們還有繼續檢測後面的位置是否可行

2.然後,我們跳出檢測的迴圈,判斷剛才迴圈的時候的那個位置是否有效。

a.如果整個迴圈下來沒有發現任何乙個有效位置的話,我們判斷他的行數是不是最後一行,如果是最後一行,並且沒有找到任何有效位置,就說明該方案不可行,直接返回即可。

b.如果我們迴圈下來有有效位置,我們就可以設定有效位置為皇后,然後判斷,改行是不是最後一行了,如果是最後一行並且有位置可以放置皇后,那我們就可以列印該方案,同時,如果有記錄可行方案的累積引數的話,我們讓引數加一。

c.如果我們找到了有效位置,但是改行不是最後一行,我們就需要繼續進入遞迴,在下一行尋找皇后的有效位置,此時傳入的列數為0,因為我們要從新開的下一行的行首開始檢測皇后的有效位置。

//傳入棋盤的狀態chess

//傳入本次開始檢測的其實位置:行數row和列數col

void eight_queen(unsigned

char *chess,int row,int col)

}if(i < 8 && row >=7)

else

if(i < 8 && row < 7)

}

#include 

#include

#include

int count=0;

#define eight_queen_set(chess,row,col) (chess[row] |= (1 << (7 & ~(col))))

void eight_queen_print(unsigned

char *chess)

putchar('\n');

}putchar('\n');

}int eight_queen_safe(unsigned

char *chess,int row,int col)

*/for(int i=0;iif(chess[i] & (1

<<(7 & ~col)))return -1;

}for(int i=row-1,j=col-1;i >= 0 && j >= 0;--i,--j)

for(int i=row-1,j=col+1;i>=0 && j<=7;--i,++j)

return0;}

void eight_queen(unsigned

char *chess,int row,int col)

}if(i < 8 && row >=7)

else

if(i < 8 && row < 7)

}int main(void)

執行結果:

no.1

0 0 0 0 0 0 0 1

0 0 0 1 0 0 0 0

1 0 0 0 0 0 0 0

0 0 1 0 0 0 0 0

0 0 0 0 0 1 0 0

0 1 0 0 0 0 0 0

0 0 0 0 0 0 1 0

0 0 0 0 1 0 0 0

no.2

0 0 0 0 0 0 0 1

0 0 1 0 0 0 0 0

1 0 0 0 0 0 0 0

0 0 0 0 0 1 0 0

0 1 0 0 0 0 0 0

0 0 0 0 1 0 0 0

0 0 0 0 0 0 1 0

0 0 0 1 0 0 0 0

no.3

0 0 0 0 0 0 0 1

0 1 0 0 0 0 0 0

0 0 0 0 1 0 0 0

0 0 1 0 0 0 0 0

1 0 0 0 0 0 0 0

0 0 0 0 0 0 1 0

0 0 0 1 0 0 0 0

0 0 0 0 0 1 0 0

……(後面的省略了)

反正總共有92種方案

八皇后問題 遞迴求解

八皇后問題簡述 在西洋棋中,皇后是最厲害的 這也就是大概為什麼不要得罪女人的原因 她可以吃掉任意與其所在列和行,以及對角線上的棋子。所以在8x8的棋盤上,安放8個皇后,使得不會相互攻擊,也就是安全的就變得極為重要。本文採用遞迴的方式,輸出所有的92種可能的方法。如下 include stdafx.h...

八皇后問題 遞迴求解

在西洋棋的棋盤上,按照西洋棋的規則,擺放8個皇后,使之 和平共處 如圖所示,在3 d上有乙個皇后,則綠色區域中都不能再放置皇后了。最暴力的方法就是使用八個for,但是很明顯,這種方法效率太低。對於放置了皇后的位置,仔細觀察棋盤可以發現每一列 行 只能有乙個皇后,每乙個主 次 對角線上也只能有乙個皇后...

遞迴求解八皇后問題

題目 八皇后問題 在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法 遞迴思路 在第1行安全位置放乙個棋子,在第2行安全位置放乙個棋子,以此類推,直到八行都放了棋子,第9行時退出遞迴過程。c 八皇后問題 在8 8格的西洋棋上擺放八個...