1. 程式人生 > >【dfs+回溯】hdu 2553 N皇后問題

【dfs+回溯】hdu 2553 N皇后問題

Source :hdu 2553 N皇后問題


Problem Description
在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。

Input
共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;如果N=0,表示結束。

Output
共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。

題意

N皇后問題,求解可行解的個數。

示例

Sample Input

1
8
5
0

Sample Output

1
92
10

思路

典型的回溯演算法
dfs1-N行,判斷是否同時滿足不同列、不同主對角線和副對角線,滿足條件的計數,開3個標記陣列,vis[ 0 ][ i ]判斷 第 i 列是否被佔、vis[ 1 ][ cur - i + 8 ]判斷主對角線、vis[ 2 ][ cur + i ]判斷副對角線。

還有,這道題要提前打表,測試資料有重複!

主對角線有 (行 - 列 )相等
87654321
98765432
109876543
1110987654
12111098765
131211109876
1413121110987
15141312111098
副對角線有 (行 + 列 )相等
23456789
345678910
4567891011
56789101112
678910111213
7891011121314
89101112131415
910111213141516

參考小白書P123

這裡寫圖片描述

參考程式碼

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<climits>
#define clr(k,v) memset(k,v,sizeof(k)) #define ll long long #define eps 1e-8 using namespace std; int n,ans,res[15]; bool vis[3][20]; void dfs(int cur){//cur表示遞迴深度,或理解為第幾行 if(cur == n + 1){//前n行已填滿 ans++; return; } for(int i = 1; i <= n; ++ i)//當前cur行,從第一個開始填 if(!vis[0][i]&&!vis[1][cur-i+n]&&!vis[2][cur+i]){ vis[0][i] = vis[1][cur-i+n] = vis[2][cur+i] = 1; dfs(cur+1); vis[0][i] = vis[1][cur-i+n] = vis[2][cur+i] = 0;//回溯 } } void init(){//初始化打表 for(int i = 1; i <= 10; ++ i){ clr(vis,0); ans = 0; n = i; dfs(1); res[i] = ans; } } int main(){ #ifndef ONLINE_JUDGE freopen("input.txt","r",stdin); #endif // ONLINE_JUDGE init(); while(scanf("%d",&n) == 1 && n){ printf("%d\n",res[n]); } return 0; }
  • 加粗 Ctrl + B
  • 斜體 Ctrl + I
  • 引用 Ctrl + Q
  • 插入連結 Ctrl + L
  • 插入程式碼 Ctrl + K
  • 插入圖片 Ctrl + G
  • 提升標題 Ctrl + H
  • 有序列表 Ctrl + O
  • 無序列表 Ctrl + U
  • 橫線 Ctrl + R
  • 撤銷 Ctrl + Z
  • 重做 Ctrl + Y