遞迴演算法之八皇后
八皇后問題核心:
1:同一行或者同一列不能放置皇后;
2:斜率為1/-1的對角線上不能有兩個皇后。
如圖:
實現原理:
#include<iostream>
#include<cstdio>
using std::cout;
using std::endl;
int count = 0;
int detection(int(*board)[8], int line, int row)//board:棋盤,line:行,row:列
{
int i;
int b1,b2;//y=kx+b
int flag1,flag2,flag3;
flag1 = flag2=flag3=0;//標誌變數
//判斷列
for (i = 0; i < 8; i++)
{
if (board[i][row] != 0)//判斷第第row列每行元素是否為0
{
flag1 = 1;//設定標誌位
break;//退出
}
}
//斜率為1/-1對角線判斷
b1 = row - line;//y=kx+b
b2 = line + row;//y=-kx+b
for (int j = 0; j <line; j++)//遍歷行
{
if (flag2 == 1)//如果找到不合理情況則沒必要繼續
break;//退出行
for (int k = 0; k < 8; k++)//遍歷列
{
if (board[j][k] == 1)//檢測j行k列中資料為1的元素
if (k - j - b1 == 0 || k + j - b2 == 0) // 如果該元素滿足該點方程則本次放置不合理(雙對角線同時檢測)
{
flag2 = 1;//設定標誌位
break;//退出本次列迴圈
}
}
}
if (flag1 || flag2 )
return 0;//只要有一種情況使得標誌位flag為1那麼久返回0;不滿足
else
return 1;//滿足返回1
}
int recursive(int(*board)[8], int line, int row)//board:棋盤,line:行,row:列 遞迴函式
{
int board2[8][8];//臨時棋盤
int n;//臨時列
for (int i = 0; i < 8;i++)//拷貝傳入遞迴中的棋盤
for (int j = 0; j < 8; j++)
board2[i][j] = board[i][j];
if (line == 8)//遞迴結束條件,第七行放置完畢line=8;
{
count++;//方法總數
for (int i = 0; i < 8; i++)//列印每一種方法
{
for (int j = 0; j < 8; j++)
cout << board[i][j] << " ";
cout << endl;
}
cout << count << endl;
}
else//遞迴呼叫
{
for (n = 0; n < 8; n++)//n:臨時列,一次窮舉每一行中符合方案的每一列的放置
{
if (detection(board2, line, n) != 0)//檢測是否可以放置
{
for (int k = 0; k < 8; k++)//將可以放的第line行其他元素清0,好處:不會存在當我們回退一級遞迴時不會出現
board2[line][k] = 0; //同一行中放置兩個1,返回上一級遞迴時我們將前一次不滿足的放置清0
board2[line][n] = 1; //放置元素
recursive(board2, line + 1, n);//不可用line++;line++會改變前一次的遞迴呼叫總的line這樣當有錯誤方案時line無法後退
} //line+1:前一級的遞迴函式中的line沒有被改變
}
}
return 0;
}
void main()
{
int board[8][8] = { 0 };
int line=0;//行
int row=0;//列
recursive(board, line, row);
system("pause");
}
轉載請標明原貼出處:https://blog.csdn.net/zj490044512