N 皇后问题(C++ 实现)

N皇后问题

把n个皇后放在n×n的国际象棋棋盘的格子上,要求任意两个皇后不能处于同一条水平线、垂直线或对角线。给出任意一个可行解。
算法:
设横纵座标的范围都是离散闭区间[0,n – 1]。
先确定每个皇后的横座标。这里通过随机方法确定,将离散闭区间[0,n – 1]的整数打乱顺序并放入一个数组。按顺序访问这个数组,尝试放置每个皇后于指定的横座标。
尝试放置第i个皇后时,纵座标也用同样的方法随机确定。尝试放置后,先进行检查,考察是否有任意两个皇后的摆放位置不符合要求。如果都符合,则尝试摆放第(i + 1)个皇后;如果不符合,则该皇后的纵座标要更改;如果这个皇后在这一列无论摆放哪个位置都不符合要求,就证明之前的摆放方案不对,更改第(i – 1)个皇后的纵座标。
如果n个皇后都能摆放完毕,算法结束。
仅当n = 1或n≥4时才有解。

在这里插入图片描述代码实现:

#include <algorithm>
#include <bitset>
#include <chrono>
#include <iostream>
#include <random>
using namespace std;

const int nmax = 1024;
struct point { int x, y; };
uniform_int_distribution<int> u(0, INT32_MAX); mt19937_64 r;
int n, x[nmax]; point c[nmax]; bitset<nmax> b[nmax];

inline bool check(int n, const int* y) {
	for (int i = 0; i < n - 1; ++i) {
		if (c[i].x == c[n - 1].x || c[i].y == c[n - 1].y || abs(c[i].x - c[n - 1].x) == abs(c[i].y - c[n - 1].y)) return false;
	}
	return true;
}

bool solve(int i) {
	if (i == n) return true;
	int* y = new int[n];
	copy(x, x + n, y); shuffle(y, y + n, r);
	for (int j = 0; j < n; ++j) {
		c[i] = { x[i], y[j] };
		if (check(i + 1, y)) {
			if (solve(i + 1)) { delete[] y; return true; }
		}
	}
	delete[] y; return false;
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	r.seed(chrono::steady_clock::now().time_since_epoch().count());
	for (;;) {
		cout << "Enter the size of the chessboard, or a single 0 to exit: ";
		cin >> n;
		switch (n) {
		case 0: return 0;
		case 1: cout << "X" << endl; break;
		case 2: case 3: cout << "No solution." << endl; break;
		default:
			for (int i = 0; i < n; ++i) { b[i].reset(); x[i] = i; }
			shuffle(x, x + n, r);
			solve(0);
			for (int i = 0; i < n; ++i) b[c[i].x][c[i].y] = true;
			for (int i = 0; i < n; ++i) {
				for (int j = 0; j < n; ++j)
					if (b[i][j]) cout << 'X';
					else cout << '.';
				cout << endl;
			}
		}
	}
}

输出示例
在这里插入图片描述在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章