算法设计与分析:世界名画陈列馆问题(可重复监视) (回溯法 分支限界法)

本文主要是介绍算法设计与分析:世界名画陈列馆问题(可重复监视) (回溯法 分支限界法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

世界名画陈列馆问题

Description:

 世界名画陈列馆由m´n个排列成矩形阵列的陈列室组成。为了防止名画被盗,需要在陈列室中设置警卫机器人哨位。每个警卫机器人除了监视它所在的陈列室外,还可以监视与它所在的陈列室相邻的上、下、左、右个陈列室。试设计一个安排警卫机器人哨位的算法,

使得名画陈列馆中每一个陈列室都在警卫机器人的监视之下,且所用的警卫机器人数最少。

设计一个优先队列式分支限界法,计算警卫机器人的最佳哨位安排,使得名画陈列馆中每一个陈列室都在警卫机器人的监视之下,且所用的警卫机器人数最少。

Input:

第一行有2 个正整数m和n (1≤m,n≤20)

Output:

 将计算出的警卫机器人数及其最佳哨位安排输出。第一行是警卫机器人数;接下来的m行中每行n个数,0 表示无哨位,1 表示哨位。

Sample Input:

4 4
Copy

Sample Output:

4
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0

!!!在各大OJ都提交了,均为超时,不是AC代码。仅作为学习参考。!!!

当y[i][j+1]==1时,以q为根的子树的解,不优于以p为根的子树的解,

当y[i][j+1]==1且y[i][j+2]==1时,以r为根的子树的解,不优于以p为根的子树的解。

搜索时应按照p、q、r或p、r、q的顺序来扩展结点。

剪枝策略:

  1. 放置的机器人个数不会超过n*m/3+1个(按每个机器人仅辐射左右或上下考虑,堆叠这样的小长条可得)。以n*m/3+2为初始最优值,当放置的个数超过当前最优值时,剪去。
  2. (当前最优值ans-当前已放置个数p)*5(最多能增加5个监视点)。如果小于未监视的格点数(n*m-spys),则一定达不到比当前最优值更好的情况,剪去。

 回溯法:

#include <stdio.h>
#include <string.h>
int n,m,f[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}}; //自己本身+上下左右 
int anx[30][30],ans; //最优结果 ans-警卫个数 anx-警卫位置 
int put[30][30],p; //暂时存储 p-警卫个数 put-警卫位置 
int spy[30][30],spys; //spy-被监视的展柜位置 spys-被监视的展柜个数 void puta(int x,int y,int p,int q);
void search(int i,int j)
{if(p>=ans) return;while(i<=n&&spy[i][j]) //已放置的不再被搜索{j++;if(j>m)	i++,j=1; //换行 }if(i>n) //更新答案{ans=p;memcpy(anx, put, sizeof(put)); //把put内容复制给anx return;}//剪枝if((ans-p)*5<=n*m-spys) return;if(i<n) puta(i+1,j,i,j);if(spy[i][j+1]==0) puta(i,j,i,j);if(j<m&&(spy[i][j+1]==0||spy[i][j+2]==0)) puta(i,j+1,i,j);
}void puta(int x,int y,int c,int d)
{put[x][y]=1;p++;for(int i=0;i<5;i++){int xx=x+f[i][0];int yy=y+f[i][1];spy[xx][yy]++;if(spy[xx][yy]==1) spys++;}search(c,d+1);put[x][y] = 0;p--;for(int i=0;i<5;i++){int xx=x+f[i][0];int yy=y+f[i][1];spy[xx][yy]--;if(spy[xx][yy]==0) spys--;}
}int main()
{scanf("%d%d",&n,&m);ans=n*m/3+2;p=0;//设置边界 for(int i=0;i<=n+1;i++)spy[i][0]=spy[i][m+1]=1;for(int i=0;i<=m+1;i++)spy[0][i]=spy[n+1][i]=1;search(1,1);printf("%d\n",ans);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)printf("%d ",anx[i][j]);printf("\n");}		
}

分支限界法:

#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int n,m,f[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}}; //自己本身+上下左右 
int anx[30][30],ans; //最优结果 ans-警卫个数 anx-警卫位置 struct Node{int pu[30][30];//pu-警卫位置 int spy[30][30]; //spy-被监视的展柜位置int i,j,k,t; //(i,j)为当前坐标 k-警卫数 t-被监视的展柜个数 
};struct cmp //重写比较函数
{bool operator() (Node a, Node b){return a.t > b.t; //小顶堆}
};
//priority_queue<Node> q; //优先队列 
priority_queue<Node, vector<Node>, cmp> q;
Node init(Node node)
{memset(node.pu,0,sizeof(node.pu)); memset(node.spy,0,sizeof(node.spy)); node.i=1;node.j=1;node.k=0;node.t=0;for(int i=0;i<=n+1;i++)node.spy[i][0]=node.spy[i][m+1]=1;for(int i=0;i<=m+1;i++)node.spy[0][i]=node.spy[n+1][i]=1;return node;
}
void puta(Node p,int x,int y)
{Node node;node=init(node);node.i=p.i;node.j=p.j;node.k=p.k+1;node.t=p.t;memcpy(node.pu, p.pu, sizeof(p.pu));memcpy(node.spy, p.spy, sizeof(p.spy));node.pu[x][y]=1;for(int d=0;d<5;d++){int xx=x+f[d][0];int yy=y+f[d][1];node.spy[xx][yy]++;if(node.spy[xx][yy]==1) {node.t++;}}while(node.i<=n&&node.spy[node.i][node.j]) //已放置的不再被搜索{node.j++;if(node.j>m)node.i++,node.j=1; //换行 }q.push(node);return;
}
int main()
{scanf("%d%d",&n,&m);ans=n*m/3+2;Node node;node=init(node);q.push(node);while(!q.empty())//队列非空 {Node p=q.top();q.pop();if(p.t>=n*m){if(p.k<ans){ans=p.k;memcpy(anx, p.pu, sizeof(p.pu)); //把put内容复制给anx }	}else{if(p.i<n) puta(p,p.i+1,p.j);if((p.i==n&&p.j==m)||p.spy[p.i][p.j+1]==0) puta(p,p.i,p.j);if(p.j<m&&(p.spy[p.i][p.j+1]==0||p.spy[p.i][p.j+2]==0)) puta(p,p.i,p.j+1);}}printf("%d\n",ans);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)printf("%d ",anx[i][j]);printf("\n");}	
}

 

这篇关于算法设计与分析:世界名画陈列馆问题(可重复监视) (回溯法 分支限界法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/858641

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

如何通过try-catch判断数据库唯一键字段是否重复

《如何通过try-catch判断数据库唯一键字段是否重复》在MyBatis+MySQL中,通过try-catch捕获唯一约束异常可避免重复数据查询,优点是减少数据库交互、提升并发安全,缺点是异常处理开... 目录1、原理2、怎么理解“异常走的是数据库错误路径,开销比普通逻辑分支稍高”?1. 普通逻辑分支 v

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基