计蒜客 - 八皇后问题
时间限制 1000ms 内存限制 65536K
题目描述
努比亚和苏丹没有子女,所以他要从一些有集成资格的继承者中挑选一个出来继承王位。他希望这个继承者足够聪明,所以他准备了一个西洋棋盘,上面的每个格子中均有一个 1-99 的数字。他又准备8个皇后棋子。
8 皇后的规则就是不能有任何棋子同行或者同列或者同斜线,在满足这个规则的同时,王位继承者还需要让 8 个皇后所在的位置的数字的和是最大的。
输入格式
输入一个数字 k (k≤20),代表棋盘的数量。
接下来有 k 个棋盘,每个棋盘有 64 个数字,分成 8 行 8 列出入,具体可见样例,每一个数字均小于 100。
输出格式
每一个棋盘对应输出最大的数值,一共输出 k 行。
样例输入
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1617 18 19 20 21 22 23 2425 26 27 28 29 30 31 3233 34 35 36 37 38 39 4041 42 43 44 45 46 47 4848 50 51 52 53 54 55 5657 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;
}

浙公网安备 33010602011771号