八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
八皇后问题可以用 dfs 来解决
第一种: 根据行 (row) 来dfs
1 #include <cstdio> 2 #include <string> 3 #include <iostream> 4 #include <algorithm> 5 #include <string.h> 6 #include <math.h> 7 8 using namespace std; 9 10 const int maxn = 100; 11 12 int vis[maxn]; 13 int cnt = 0; 14 15 bool check(int row,int col) 16 { 17 for (int i=0;i<row;i++) 18 { 19 if (vis[i] == col || abs(vis[i] - col) == abs(i-row)) 20 return false; 21 } 22 return true; 23 } 24 25 void dfs(int row) // row代表搜索到第几行 26 { 27 if (row == 8) 28 { 29 cnt++; 30 return ; 31 } 32 else 33 { 34 for (int col = 0;col<8;col++) 35 { 36 if (check(row,col)) 37 { 38 vis[row] = col; 39 dfs(row+1); 40 } 41 } 42 } 43 } 44 45 int main() 46 { 47 dfs(0); 48 printf("%d\n",cnt); 49 return 0; 50 }
方法二:
根据列 (col) 来dfs
1 #include <cstdio> 2 #include <string> 3 #include <iostream> 4 #include <algorithm> 5 #include <string.h> 6 #include <math.h> 7 8 using namespace std; 9 10 const int maxn = 100; 11 12 int vis[maxn],a[maxn][maxn]; 13 int cnt = 0; 14 15 16 bool check(int row,int col) 17 { 18 for (int i=0;i<col;i++) 19 { 20 if (vis[i] == row || abs(vis[i] - row) == abs(i-col)) 21 return false; 22 } 23 return true; 24 } 25 26 void dfs(int col) //col代表搜索到第几列 27 { 28 if (col == 8) 29 { 30 cnt++; 31 return ; 32 } 33 else 34 { 35 for (int row = 0;row<8;row++) 36 { 37 if (check(row,col)) 38 { 39 vis[col] = row; 40 dfs(col+1); 41 } 42 } 43 } 44 } 45 46 int main() 47 { 48 dfs(0); 49 printf("%d\n",cnt); 50 return 0; 51 }
VJudge上的一道八皇后的问题:
在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。Input无输入。Output按给定顺序和格式输出所有八皇后问题的解(见Sample Output)。
无输入。
Sample Output
No. 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 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 0 No. 2 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 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 No. 3 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 No. 4 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 No. 5 0 0 0 0 0 1 0 0 1 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 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 No. 6 0 0 0 1 0 0 0 0 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 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 No. 7 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 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 No. 8 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 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 No. 9 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 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 ...以下省略
思路:其实就是多了一个标记数组和一个 print 函数
AC代码:
1 #include <cstdio> 2 #include <string> 3 #include <iostream> 4 #include <algorithm> 5 #include <string.h> 6 #include <math.h> 7 8 using namespace std; 9 10 const int maxn = 100; 11 12 int vis[maxn],a[maxn][maxn]; 13 int cnt = 0; 14 int t = 1; 15 16 17 void print() 18 { 19 cout << "No. " << t++ << endl; 20 for (int i=0;i<8;i++) 21 { 22 for (int j=0;j<8;j++) 23 { 24 cout << a[i][j] << ' '; 25 } 26 printf("\n"); 27 } 28 } 29 30 31 bool check(int row,int col) 32 { 33 for (int i=0;i<col;i++) 34 { 35 if (vis[i] == row || abs(vis[i] - row) == abs(i-col)) 36 return false; 37 } 38 return true; 39 } 40 41 void dfs(int col) 42 { 43 if (col == 8) 44 { 45 print(); 46 return ; 47 } 48 else 49 { 50 for (int row = 0;row<8;row++) 51 { 52 if (check(row,col)) 53 { 54 vis[col] = row; 55 a[row][col] = 1; 56 dfs(col+1); 57 a[row][col] = 0; 58 } 59 } 60 } 61 } 62 63 int main() 64 { 65 dfs(0); 66 return 0; 67 }