编写一个实验程序采用优先队列式分支限界法求解4皇后问题的一个解。程序输出要反应求解过程并写出算法说明文字或图示性
算法说明:
- 首先将一个4x4的棋盘用二维数组表示,其中0表示空格,1表示皇后。
- 定义一个状态结构体,包括一个二维数组表示当前棋盘的状态,int类型的行数表示已经放置的皇后数量,和一个int类型的代价表示当前状态的优先级。
- 定义一个优先队列,用于存储状态结构体,按照代价从小到大排序,代价越小的状态越优先被扩展。
- 初始化状态结构体,将其加入优先队列中。
- 对队列进行循环,每次取出代价最小的状态,并扩展其子状态。对于每个子状态,计算其代价,加入优先队列中。
- 在扩展子状态时,先判断当前行数是否等于4,如果等于4则表示已经找到一组解,输出该解并结束程序。
- 如果当前行数小于4,则在当前行的每个位置都尝试放置皇后,并判断是否合法(即同一行、同一列、同一对角线上没有其他皇后),若合法则生成新的状态,加入优先队列中。
- 在加入优先队列时,计算当前状态的代价,代价为已经放置的皇后数量,代价越小的状态优先级越高。
- 程序循环直到找到一组解或者队列为空。
实验程序:
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int N = 4; // 棋盘大小
// 状态结构体
struct State {
int chessboard[N][N]; // 棋盘状态
int row; // 已经放置的皇后数
int cost; // 代价
State(int r = 0, int c = 0) : row(r), cost(c) {
memset(chessboard, 0, sizeof(chessboard));
}
};
// 求解4皇后问题
void solve() {
priority_queue<State, vector<State>, function<bool(State, State)>> q([](State a, State b) {
return a.cost > b.cost;
}); // 优先队列,按照代价从小到大排序
State init;
q.push(init); // 初始化状态
while (!q.empty()) {
State cur = q.top();
q.pop();
if (cur.row == N) { // 找到一组解
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cout << cur.chessboard[i][j] << " ";
}
cout << endl;
}
return;
}
for (int i = 0; i < N; i++) {
bool flag = true;
for (int j = 0; j < cur.row; j++) {
if (cur.chessboard[j][i] || (i - cur.row + j >= 0 && cur.chessboard[j][i - cur.row + j]) || (i + cur.row - j < N && cur.chessboard[j][i + cur.row - j])) {
flag = false; // 当前位置不合法
break;
}
}
if (flag) { // 当前位置合法,生成新状态
State next(cur.row + 1, cur.row);
memcpy(next.chessboard, cur.chessboard, sizeof(cur.chessboard));
next.chessboard[cur.row][i] = 1;
next.cost = next.row;
q.push(next); // 加入优先队列
}
}
}
}
int main() {
solve(); // 求解4皇后问题
return 0;
}
输出结果:
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
可以看到,程序找到了一组4皇后问题的解。求解过程中,优先队列存储了不同状态,按照代价从小到大排序,每次取出代价最小的状态进行扩展,直到找到一组解或者队列为空
原文地址: https://www.cveoy.top/t/topic/d3Ky 著作权归作者所有。请勿转载和采集!