基础练习 2n皇后问题

来源:互联网 发布:public static json 编辑:程序博客网 时间:2024/05/17 15:40
问题描述
  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
  输入的第一行为一个整数n,表示棋盘的大小。
  接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
  输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0

思路:
       回溯法,八皇后问题变形,Dfs与八皇后一样,详细请见回溯法。八皇后问题只需要找出解的个数,这道题还需要把解的路径记录下来,然后假设白皇后在第i行,则黑皇后只能在第i+x(x=0、1、...)行,如果白皇后和黑皇后所在的两行不是互斥(白皇后能放置的行黑皇后不能放置为互斥)行,则解的个数加一,即排除白皇后和黑皇后虽然在第一行放置的是不同列,但是后续几行可能放置在同一个格子的情况,得到的解乘2即是答案。
       注意:vis[][]的数组一定要开的足够大。

#include <cstdio>#include <cstring>int tot, c[10], n, num;                         int map[10][10];int vis[100][10];void Dfs(int cur){if(cur == n)                           { for(int f = 0; f < n; f++)vis[tot][f] = c[f];tot++; }else{for(int i = 0; i < n; i++)         {if(map[cur][i] == 1){int ok = 1;c[cur] = i;                    for(int j = 0; j < cur; j++)   {if(c[cur] == c[j] || cur - c[cur] == j - c[j] || cur + c[cur] == j + c[j]){ok = 0;break; } } if(ok)Dfs(cur + 1);} } }}bool isMutexLine(int a[], int b[]) //判断两行是否互斥{for(int i = 0; i < n; i++){if(a[i] == b[i])    //黑白皇后在同一格return true;}return false;} void Search(int x)               {for(int q = 0; q < x; q++){for(int w = q + 1; w < x; w++)if(!isMutexLine(vis[q], vis[w]))num++;}printf("%d", 2 * num);}int main(){//freopen("input6.txt", "r", stdin);//freopen("output777.txt", "w", stdout); int i, j;scanf("%d", &n);for(i = 0; i < n; i++)for(j = 0; j < n; j++)scanf("%d", &map[i][j]);memset(c, -1, sizeof(c));memset(vis, -1, sizeof(vis));tot = 0;num = 0;Dfs(0);Search(tot);//printf("%d\n", tot);//printf("%d\n", ans);return 0;}



1 0
原创粉丝点击