递归应用:八皇后问题
八皇后問題介紹
八皇后問題是一個以國際象棋為背景的問題:如何能夠在 8×8 的國際象棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處于同一條橫行、縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題:這時棋盤的大小變為n1×n1,而皇后個數也變成n2。而且僅當 n2 = 1 或 n1 ≥ 4 時問題有解。下圖是一個八皇后圖解。
八皇后問題分析
八皇后問題,是一個古老而著名的問題,是回溯算法的典型案例。同樣利用遞歸算法也可以求解,今天我們采用遞歸的思想來求解八皇后問題。放第1個皇后時,我們可以在第一行任意位置擺放,放第2個皇后,肯定是在第二行 此時要考慮是否能被第1個皇后攻擊到,也就能否被列攻擊 或者斜線攻擊到,同樣我們擺放第3行的皇后時,也要考慮是否能否被已經擺放好的皇后列攻擊和斜線攻擊到!擺放每一行的皇后,都要考慮,能否被已經擺放好的皇后列攻擊或者斜線攻擊到。難道不可以用遞歸思想嗎?當然可以了。我們將n*n的棋盤數據,初始化數據為0,擺放第i行時(i從0開始)第j列(j從0開始),如果該位置是安全的,就將數據置為1,然后繼續擺放第i+1行,這樣遞歸直到,第n行,到第n行 已經把n個皇后擺放ok,打印棋盤。
遞歸代碼展示
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> static count = 0;//計數 #define ROWNUM 8 //行數量 #define COLNUM 8 //列數量 可以拓展為n皇后問題//chess 棋盤現有數據 //row 行下標 0 ~ 7 //col 列下標 0 ~ 7 int IsSafe(int(*chess)[COLNUM], int row,int col) {int flag = 1;//默認安全//判斷內否被第i行第col列攻擊到for (int i = 0; i < row; i++){//該列已經有皇后,可以被攻擊到if (1 == chess[i][col]){flag = 0;break;}}//因為擺放皇后是從新的一行開始,不存在行攻擊//斜線攻擊,分左上、右上 能否被攻擊到。沒有左下和右下方,因為后面的皇后棋子還沒開始擺放!//判斷能否被左上斜線攻擊for (int i = row - 1, j =col-1; i >= 0 && j >= 0; i--, j--){//該斜線上已經有皇后,可以被攻擊到if (1 == chess[i][j]){flag = 0;break;}}//判斷能否被右上斜線攻擊for (int i = row - 1, j = col+1; i >= 0 && j < COLNUM; i--, j++){//該斜線上已經有皇后,可以被攻擊到if (1 == chess[i][j]){flag = 0;break;}}return flag; }/* 在8×8格的國際象棋上擺放八個皇后,使其不能互相攻擊, 即任意兩個皇后都不能處于同一行、同一列或同一斜線上,問有多少種擺法。 高斯認為有76種方案,高斯 先生也沒有算對的時候! */ //chess 棋盤數據 //row 行下標 0 ~ 7 void EightQueen(int(*chess)[COLNUM], int row) {int thiz[ROWNUM][COLNUM] = { 0 };//到row行時的棋盤數據for (size_t i = 0; i < ROWNUM; i++){for (size_t j = 0; j < COLNUM; j++){thiz[i][j] = chess[i][j];}}//row 從0 行到 第 7行 if (ROWNUM == row)//棋盤已經排好完畢,打印棋盤,遞歸函數出口。{count++;printf("第%d種擺放方法:\n",count);for (size_t i = 0; i < ROWNUM; i++){for (size_t j = 0; j < COLNUM; j++){printf("%d ", thiz[i][j]);}printf("\n");}printf("\n");}else{//將棋子擺放在 第row行的第i列for (size_t i = 0; i < COLNUM; i++){//先將該行清空for (size_t i = 0; i < COLNUM; i++){thiz[row][i] = 0;}//判斷該位置是否合法是否安全,能否被已經擺好的皇后攻擊到。if (IsSafe(thiz, row, i)){thiz[row][i] = 1;//在安全位置擺放皇后//繼續在下一行擺放皇后,進行遞歸調用。EightQueen(thiz, row+1);}}}}int main(int argc, char *argv[]) {int chess[ROWNUM][COLNUM] = { 0 };//從第0行開始遞歸EightQueen(chess,0);printf("總共%d種擺放方法。\n",count);return 0; }運行結果檢測
當行列數為1、2、3時無法進行擺放。
當行列數n = 4時,也就是四皇后,共2種擺放方式。
當行列數n = 8時,也就是八皇后,共92種擺放方式。
總結
以上是生活随笔為你收集整理的递归应用:八皇后问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iFit—Smart Cardio Eq
- 下一篇: mapping数据列表