什麼是八皇后問題?例如,下面的這種擺法(0表示沒有皇后,1表示擺放了皇后):10該問題是國際西洋棋棋手馬克斯·貝瑟爾於2023年提出:在8×8格的西洋棋上擺放八個皇后,使其不能互相攻擊。
所以,我們要了解皇后的攻擊模式:皇后可以橫著走任意步數、豎著走任意步數、斜著走任意步數。
翻譯過來就是:即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。(實際上,總共有 92種擺法 )
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]也沒問題)問題2:八皇后的列印為什麼呢?char型別為8bit,所以總共就有8*8bit,其中,我們讓有皇后的位置標記為1,讓沒有皇后的位置標記為0
我們把八皇后的列印單獨寫乙個函式,模組化方便定位錯誤。
int count=0;//累積八皇后的方案個數,是乙個全域性變數
void eight_queen_print(unsigned
char *chess)
putchar('\n');
}putchar('\n');
}
列印出來的格式可能是:
no.92問題3:八皇后的和平相處(如何判斷該位置是否可以放置乙個皇后)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
1.首先,我們把有皇后的位置標記為1,把沒有皇后的位置標記為02.其次,我們寫乙個函式單獨檢測該位置是否可以放置皇后:
—— 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.10 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格的西洋棋上擺放八個...