其他分享
首页 > 其他分享> > 博物馆守卫问题(世界名画展览馆)

博物馆守卫问题(世界名画展览馆)

作者:互联网

世界名画展览馆(博物馆守卫问题)

在某博物馆中摆放了非常重要的文物,为了节省人力,该博物馆专门购买了警卫机器人来看管这些文物。该博物馆的房间排列整齐,房间的大小相同。每个警卫机器人能够巡查的范围除本身所在房间外,还包括其起始安放的房间的上下左右四个房间。为了减少摆放的机器人的数量,请你设计一种最佳的摆放方案,使得摆放的机器人数量最少。
输入:
输入一行,有两个整数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