您的位置:首页 > 其它

64-八皇后问题

2018-03-26 22:31 113 查看

问题描述:

努比亚和苏丹没有子女,所以他要从一些有集成资格的继承者中挑选一个出来继承王位。他希望这个继承者足够聪明,所以他准备了一个西洋棋盘,上面的每个格子中均有一个 1-99 的数字。他又准备8个皇后棋子。

8 皇后的规则就是不能有任何棋子同行或者同列或者同斜线,在满足这个规则的同时,王位继承者还需要让 8 个皇后所在的位置的数字的和是最大的。


输入格式

输入一个数字 k (k≤20),代表棋盘的数量。

接下来有 k 个棋盘,每个棋盘有 64 个数字,分成 8 行 8 列出入,具体可见样例,每一个数字均小于 100。


输出格式

每一个棋盘对应输出最大的数值,一共输出 k 行。

样例输入

1  2  3  4  5  6  7  8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
48 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64


样例输出

260


代码解析:

思路一:

      利用回溯法求解所有八皇后问题的解,把每组解对应的数值之和计算出来然后取最大就是最终的结果。这里写下我自己的回溯法过程,用递归函数来实现。

      首先,从第0行开始依次向下在每行放入一个皇后,当前位置可以放入皇后时就去在下一行继续尝试放入皇后,当前位置不可放入皇后即有同列或同斜线的皇后存在时,回退到上一行的皇后位置,让该位置向右移动一位,继续尝试下一行。当所有行都被放入皇后时说明求出一组解,更新答案。

      用一个数组x来记录放入皇后的位置,x[i]表示第i行的皇后放在了第x[i]列的位置,未放入时x[i]=-1。求解问题的递归函数是void queen(int k),当k==n时说明8行里全部放入皇后,更新结果,结束递归。否则,在没有冲突即之前已经放入的皇后的位置和当前位置不不同列,不同斜线(判断条件: 斜线的斜率绝对值==1)时在该位置放入皇后并尝试下一行。Bool notDanger(int r,int c) 是判断当前位置是否有冲突的函数。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int n = 8;

int tmp, ans;
int x[10];
int chess[10][10];

bool notDanger(int r, int c) {
for (int i = 0; i < r; i++) {
if (x[i] == c) return false;
if (abs(r - i) == abs(c - x[i])) return false;
}
return true;
}

void queen(int k) {//放入第k行的皇后
if (k == n) { ans = max(ans, tmp); return; }//所有行都尝试完毕,即求出了相应一组解

for (int i = 0; i < n; i++) {
if (notDanger(k, i)) {//没有冲突,尝试下一行
x[k] = i;
tmp += chess[k][i];
queen(k + 1);
x[k] = -1;//注意下层递归结束后及时更新相应变量值
tmp -= chess[k][i];
}
}
}

int main() {
int t;
scanf("%d", &t);
while (t--) {
tmp = ans = 0;
memset(x, -1, sizeof(x));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
scanf("%d", &chess[i][j]);
}
queen(0);
printf("%d\n", ans);
}
return 0;
}


方法二:

#include <cstdio>
#include <iostream>
using namespace std;
int n = 0;//棋盘大小
int ans = 0;//解的个数
bool hashTable[20] = {false};//hashtable[i] == true表示第i列被占用
bool xy[20] = {false};//左下-右上
bool yx[20] = {false};
int val[100][100];
int maze[100][100];

int P[20] = {0};//临时存放情况
void dfs(int deep) {
if (deep >= n) {
for (int i = 0; i < n; i++) {
val[ans][i] = P[i];
}
ans++;
return;
}
for (int i = 0; i < n; i++) {
if (xy[i+deep] == false && yx[i-deep+n] == false && hashTable[i] == false) {
xy[i+deep] = true;
yx[i-deep+n] = true;
hashTable[i] = true;
P[deep] = i;
dfs(deep+1);
hashTable[i] = false;
yx[i-deep+n] = false;
xy[i+deep] = false;
}
}
}
int main() {
// cin >> n;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
cin >> maze[i][j];
}
}

n = 8;
dfs(0);

int maxn = 0;
for (int i = 0; i < ans; i++) {
int mmmaxn = 0;
for (int j = 0; j < n; j++) {
// printf("%d ", val[i][j]);
mmmaxn += (maze[j][val[i][j]]);
}
maxn = max(maxn, mmmaxn);
}
printf("%d\n", maxn);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: