2n皇后问题
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
首先考虑n皇后问题,用回溯法(dfs)
int n; int vis[8][8];//记录是否放皇后 void dfs(int i) { int j, k; if (i == n) { return; } for (j = 0; j < n; j++) { int flag = 1;//皇后不冲突 if (vis[i][j] != 1) continue; for (k = 0; k < 8; k++)//判断该列列 if (vis[k][j] == 2) flag = 0; for (k = 1; i - k >= 0 && j - k >= 0; k++)//判断左上线 if (vis[i - k][j - k] == 2)flag = 0; for (k = 1; i - k >= 0 && j + k < 8; k++)//判断右上线 if (vis[i - k][j + k] == 2)flag = 0; if (flag == 1) { vis[i][j] = 1;//标记皇后 dfs(i + 1);//判断下一行 vis[i][j] = 0;//取消标记 } } }
在白皇后成立的基础上,考虑黑皇后,因此在dfs1中判断条件应做修改:
if (flag == 1) { vis[i][j] = 2;//白皇后标记为2 dfs(i + 1); vis[i][j] = 1;//空格标记为1,0的地方跳过 }
当(i==n)即白皇后都放完后,进行dfs2,方法同dfs1,黑皇后标记为3即可
AC代码
#include <iostream> using namespace std; int vis[8][8], n,ans=0; void dfs2(int i) { int j, k; if (i == n) { ans++; return; } for (j = 0; j < n; j++) { int flag = 1; if (vis[i][j] != 1) continue; for (k = 0; k < 8; k++)//列 if (vis[k][j] == 3) flag = 0; for (k = 1; i - k >= 0 && j - k >= 0; k++)//左上线 if (vis[i - k][j - k] == 3)flag = 0; for (k = 1; i - k >= 0 && j + k < 8; k++)//右上线 if (vis[i - k][j + k] == 3)flag = 0; if (flag == 1) { vis[i][j] = 3; dfs2(i + 1); vis[i][j] = 1; } } } void dfs(int i) { int j, k; if (i == n) { dfs2(0); return; } for (j = 0; j < n; j++) { int flag = 1; if (vis[i][j] != 1) continue; for (k = 0; k < 8; k++)//列 if (vis[k][j] ==2) flag = 0; for (k = 1; i - k >= 0 && j - k >= 0; k++)//左上线 if (vis[i - k][j - k] ==2)flag = 0; for (k = 1; i - k >= 0 && j + k < 8; k++)//右上线 if (vis[i - k][j + k] == 2)flag = 0; if (flag == 1) { vis[i][j] = 2; dfs(i + 1); vis[i][j] = 1; } } } int main() { int i,j; cin >> n; for (i = 0; i < n; i++) for (j = 0; j < n; j++) cin >> vis[i][j]; dfs(0); cout << ans; return 0; }

浙公网安备 33010602011771号