八皇后问题(又名: 高斯八皇后)

浪尽此生 提交于 2020-02-06 03:26:48

题目连接: 八皇后问题

题目:

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b 1b 2…b 8,其中b i为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

Input
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

Output
输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

Sample Input
2
1
92

Sample Output
15863724
84136275

注: 字符串中的数字表示不同行上的列坐标 例如15863724的含义是八个皇后分别位于(1, 1), (2, 5), (3, 8), (4, 6), (5, 3), (6, 7), (7, 2), (8, 4)处.

解题思路:

本题是DFS算法的一道经典例题, 一共8*8的棋盘要放8个皇后, 并且他们彼此还无法相互攻击,
那么我们很容易得到一个结论: 8个皇后一定处于8个不同行上, 也处于8个不同列上.因此我们可以通过一个整型一维数组来记录不同行上皇后所处的列.
当进行搜索时, 我们不妨就让第n个皇后处于第n行上, 然后判断该列8个位置能否放置该皇后, 若可以则继续深入, 直到8个皇后都放置好时进行结果记录.
由于一共92种结果顺序是一定的, 因此我们可以进行结果预处理.

AC代码:

#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <queue>
#define ll long long
using namespace std;
int location[10]; //皇后位置记录
string result[100];
int cou = 0; //结果统计
bool check(int x, int y) //检查该位置是否能放皇后
{
	for (int i = 1; i < x; i++) {
		if (location[i] == y) return 0; //处于同一列, 不符合条件
		if (location[x - i] == y - i || location[x - i] == y + i) return 0; //处于对角, 不符合条件
	}
	return 1;
}
void dfs(int n) //n表示当前要放第n个皇后, 我要把他放在第n行上
{
	if (n == 9) { //当函数进入达到第九层时, 说明8个皇后都已经安放好, 进行结果记录
		for (int i = 1; i <= 8; i++) {
			result[cou] += location[i] + '0'; //要存放成字符型, 所以要加上'0'
		}
		cou++;
		return;
	}
	
	for (int i = 1; i <= 8; i++) { //尝试把这个皇后放在不同列上
		if (check(n, i)) {
			location[n] = i;
			dfs(n + 1);
		}
	}
}
int main(void)
{
	dfs(1); //跑出全部的结果
	int t;
	scanf("%d", &t);
	while (t--) {
		int n;
		scanf("%d", &n);
		cout << result[n-1] << endl;
	}
	return 0;
}

由于本题的特殊性, 即我们明白8个皇后一定分别处于不同行列上, 所以可以略去回溯步骤, 但是在深搜中回溯是常常与其相伴的.

END

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!