计蒜客 - 八皇后问题

时间限制 1000ms 内存限制 65536K

题目描述

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

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

输入格式

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

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

输出格式

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

样例输入

1
 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;
}

posted @ 2017-10-24 23:16  不想吃WA的咸鱼  阅读(387)  评论(0编辑  收藏  举报