2636: 回溯法-世界名画陈列馆问题
金币值:3
定数:10
时间限制:1.000 s
内存限制:128 M
正确:2
提交:2
正确率:100.00% 命题人:
题目描述
针对世界名画陈列馆问题,设计一个算法,计算警卫机器人的最佳哨位安排,使得名画陈列馆的每个陈列室都在警卫机器人监视之下,且所用的警卫机器人数目最少。要求用回溯法。已知一个机器人除了可以监控它所在的陈列室之外,还可以监控上、下、左、右4个方位的陈列室。
例如,5行5列的陈列室至少需要7个机器人。
0 0 0 1 0
1 1 0 0 0
0 0 0 0 1
0 0 1 0 0
1 0 0 1 0
例如,5行5列的陈列室至少需要7个机器人。
0 0 0 1 0
1 1 0 0 0
0 0 0 0 1
0 0 1 0 0
1 0 0 1 0
测试代码 复制
#include <stdio.h>
int m,n; //全局变量分别表示世界名画陈列馆中有m行n列个陈列室
int bestx[12][12]; //存储最优解,0号单元不用
int x[12][12]; //存储当前解,0号单元不用
int y[12][12]; //表示世界名画陈列馆中的陈列室受到机器人监控的次数
int bestNumber, currentNumber; //全局变量分别表示递归过程中当前找到的最优值以及当前值
void change(int i, int j) {
x[i][j]=1;
y[i][j]++;
y[i-1][j]++;
y[i+1][j]++;
y[i][j-1]++;
y[i][j+1]++;
currentNumber++;
}
void restore(int i, int j) {
x[i][j]=0;
y[i][j]--;
y[i-1][j]--;
y[i+1][j]--;
y[i][j-1]--;
y[i][j+1]--;
currentNumber--;
}
void Backtrack(int i, int j) {
while (y[i][j]!=0 && i<=m) { //如果已经受到监视,则不放哨兵
j++;
if (j>n) { //从下一行开始
i++;
j=1;
}
}
if (i>m) { //递归出口,更新最优解和最优值
for(int ii=1; ii<=m; ii++) {
for (int jj=1; jj<=n; jj++) {
bestx[ii][jj]=x[ii][jj];
}
}
bestNumber = currentNumber;
} else { //分为三种情况:(i+1,j),(i,j),(i,j+1)
if (i<m && currentNumber<bestNumber) {// case1
}
if (currentNumber<bestNumber) {// case2
}
if (j<n && currentNumber<bestNumber) { //case3
}
}
}
void init() {
int i,j;
bestNumber=m*n; // 机器人数量不可能超过陈列室的个数
currentNumber=0;
for(j=0; j<=n+1; j++) {// 简化边界条件,假设存在第0行和第m+1行陈列室且已经受到监控
y[0][j]=1;
y[m+1][j]=1;
}
for(i=0; i<=m+1; i++) {// 简化边界条件,假设存在第0列和第n+1列陈列室且已经受到监控
y[i][0]=1;
y[i][n+1]=1;
}
for(i=1; i<=m; i++) {
for(j=1; j<=n; j++) {
y[i][j]=0; //初始化世界名画陈列馆中的所有陈列室没有受到监控
}
}
}
int main(void) {
scanf("%d %d",&m,&n);
init();
Backtrack(1,1);
printf("%d\n", bestNumber);
return 0;
}
输入格式
第1行输入两个整数,分别表示世界名画陈列馆中有m行n列个陈列室(假设1<=m,n<=10)。
输出格式
第1行输出1个整数,表示最少需要机器人的数量。
输入样例 复制
4 4
输出样例 复制
4