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

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

世界名画陈列馆问题

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/397740

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家,并整理七大洲和这些国家的KML矢量数据分析分享给大家,如果你需要这些数据,请在文末查看领取方式。 世界上横跨两大洲的国家 地球被分为七个大洲分别是亚洲、欧洲、北美洲、南美洲、非洲、大洋洲和南极洲。 七大洲示意图 其中,南极洲是无人居住的大陆,而其他六个大洲则孕育了众多国家和

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.