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

輸出示例
在這裏插入圖片描述在這裏插入圖片描述

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