博物馆守卫问题(世界名画展览馆)
作者:互联网
世界名画展览馆(博物馆守卫问题)
在某博物馆中摆放了非常重要的文物,为了节省人力,该博物馆专门购买了警卫机器人来看管这些文物。该博物馆的房间排列整齐,房间的大小相同。每个警卫机器人能够巡查的范围除本身所在房间外,还包括其起始安放的房间的上下左右四个房间。为了减少摆放的机器人的数量,请你设计一种最佳的摆放方案,使得摆放的机器人数量最少。
输入:
输入一行,有两个整数m,n,分别表示该博物馆每行的房间数和每列的房间数。博物馆总房间数即为m*n。
输出:
输出的第一行表示需要的机器人的数量,其后m行,每行有n个元素,每个元素的值为0或1,分别表示对应的房间是否摆放机器人。0表示不摆放,1表示需要摆放。
样例输入:
4 4
样例输出:
4
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0
对于此题有不少的解法,以下代码属于时间复杂度较高的一种做法,使用的优先队列,但如果输入5x5的话可能跑不起来,仅用于自己学习。
未经作者授权,禁止转载或作他用。
#include"algorithm.h"
#include<queue>
#define max 100
using namespace std;
int col = 0;
int row = 0;
int board[max][max];
// 记录最优的放置个数: n*m/3 - 1
int best;
int ans_; // 记录个数
int ans2[max][max];
struct node {
// 棋牌的状态,
// board[i][j]=0 表示没有任何处理,
// = 1 放置守卫
// = 2 被监视
int board[max][max];
int x, y; // 当前守卫放置的位置
int sum; // 守卫的总个数
node(int board[max][max], int x, int y, int sum) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++){
// 拷贝原有的状态
this->board[i][j] = board[i][j];
}
}
this->board[x][y] = 1; // 放置守卫
// 添加该守卫监视的位置
if (x - 1 >= 0) {
if(this->board[x - 1][y] == 0)
this->board[x - 1][y] = 2;
}
if (x + 1 < row) {
if(this->board[x + 1][y] == 0)
this->board[x + 1][y] = 2;
}
if (y - 1 >= 0) {
if (this->board[x][y - 1] == 0)
this->board[x][y - 1] = 2;
}
if (y + 1 < col) {
if(this->board[x][y + 1] == 0)
this->board[x][y + 1] = 2;
}
this->sum = sum + 1;
this->x = x;
this->y = y;
}
// 重载运算符号,如果a<b 表示 a状态使用的机器人数量多于 b使用的
friend bool operator <(node a, node b) {
return a.sum > b.sum;
}
};
void print2DArray(int const nums[][max], int m, int n) {
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++) {
printf("%3d", nums[i][j]);
}
printf("\n");
}
}
// 初始化一个优先队列
void solution() {
priority_queue<node> q;
memset(board, 0, sizeof board);
best = row * col / 3 + 1;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++){
// 第一层的情况
q.push(node(board, i, j, 0));
}
}
// 是否所有的都已经监视
int flag = 0;
while (!flag && !q.empty()) {
// 第一步:获取头结点,活结点
node temp = q.top();
q.pop();
// 限制界限
if (temp.sum > best) continue;
int tempBoard[max][max];
memcpy(tempBoard, temp.board, sizeof tempBoard);
// tFlag ==1 表示所有的位置都已经被监控了
int tFlag = 1;
// 生成子状态,自棋盘
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (tempBoard[i][j] == 0) {
// 如果等于说明没有被监视,可以加入守卫
node n = node(tempBoard, i, j, temp.sum);
q.push(n);
tFlag = 0;
}
}
}
if (tFlag) {
flag = 1;
ans_ = temp.sum;
memcpy(ans2, temp.board, sizeof temp.board);
}
}
}
int main() {
ans_ = 0;
memset(ans2, 0, sizeof ans2);
cin >> row >> col;
solution();
cout << ans_ << endl;
print2DArray(ans2, row, col);
return 0;
}
附上一张自己理解的图片:
未经作者授权,禁止转载或作他用。
标签:展览馆,int,max,sum,++,守卫,board,名画,row 来源: https://blog.csdn.net/hhhmonkey/article/details/112972966