概述
今天也终于领略到什么是深搜什么是广搜的区别和特点了,其实一直不太懂什么时候用深搜,什么时候用广搜,虽然两种都有用过,但是都是结合解题报告或者其他途径来做的,总感觉深搜用起来比较顺手,感觉很多题都可以用深搜来解决,但是今天遇到的这个题用深搜怎么想方设法都不好用,结果应该正确,但是就是TimeLimit,只好用广搜来解了,也颇费周折的各方面查资料知道了广搜一般用在有这样的提示:最短时间或者最短路径,或许这就是基本层面但很有用处的区别,现在的理解就到这里了,另外其他学术性的区别见博客:http://blog.csdn.net/u014665013/article/details/39558093
声明一下:优先队列和队列的区别,优先队列是能通过优先级来限定队列的顺序的,但是队列只能是先进先出,不能按照参数来限定顺序 ,这里用到的是优先队列
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1242
贴一下用深搜做的TimeLimit的代码,毕竟是经过一番思考的... 从四个方向深搜..
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
int sum=0, row,line,doorrow,doorline,startrow,startline,count=0,mark=0;
char ch[205][205]={0};
void find(int i,int j){
if(doorrow==i&&doorline==j){ //注意最后一次到达的时候会将a还原时改为'.' ,但是不妨碍
if (mark==0||sum<count) {
mark=1;
count=sum;
}
}
else {
if(i>0&&ch[i-1][j]!='#'){
char temp='.';
sum++;
if(ch[i-1][j]=='x') sum++,temp='#';//如果是守卫,需要用1单位时间来杀掉他
ch[i-1][j]='#';
find(i-1,j);
if(temp=='#') sum--,ch[i-1][j]='x';
else ch[i-1][j]='.';
sum--;
}
if(i<row-1&&ch[i+1][j]!='#'){
char temp='.';
sum++;
if(ch[i+1][j]=='x') sum++,temp='#';
ch[i+1][j]='#';
find(i+1,j);
if(temp=='#') sum--,ch[i+1][j]='x';
else ch[i+1][j]='.';
sum--;
}
if(j>0&&ch[i][j-1]!='#'){
char temp='.';
sum++;
if(ch[i][j-1]=='x') sum++,temp='#';
ch[i][j-1]='#';
find(i,j-1);
if(temp=='#') sum--,ch[i][j-1]='x';
else ch[i][j-1]='.';
sum--;
}
if(j<line-1>0&&ch[i][j+1]!='#'){
char temp='.';
sum++;
if(ch[i][j+1]=='x') sum++,temp='#';
ch[i][j+1]='#';
find(i,j+1);
if(temp=='#') sum--,ch[i][j+1]='x';
else ch[i][j+1]='.';
sum--;
}
}
}
int main (){
while(~scanf("%d%d",&row,&line)){
sum=0,mark=0,count=0; //别忘了每次都要初始化
for(int i=0;i<row;i++)
scanf("%s",ch[i]);
for(int i=0;i<row;i++)
for(int j=0;j<line;j++){
if(ch[i][j]=='a')
doorrow=i,doorline=j;
if(ch[i][j]=='r')
startrow=i,startline=j;
}
find(startrow,startline);
if(count==0)
printf("Poor ANGEL has to stay in the prison all his life.n");
else
printf("%dn",count);
}
return 0;
}
使用广搜(使用优先级队列,因为两者好像不可分的),通过优先级队列的排序功能控制逐层进行遍历。
这里又悟出了深搜和广搜的一点不同:
现在知道为什么用宽度搜索了,(1)如果深度搜索的话,会沿着一条路径走到头,包括中间有很多分叉路,这样只有走到头才会停止本次搜索,但是宽度搜索就不一样了,他会按照层数进行查找,这样可以使一些不正确的路径不会走到头,相当于节省了这部分时间,所以相对来书效率就高了。
(2)另外深搜和广搜另外一个很大的不同好像也在于,深搜一般是递归调用函数,这样深搜;但是广搜则是没有递归调用函数,而是通过优先队列来通过循环实现的,这应该也是一个很大的不同吧
广搜代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#define N 201
using namespace std;
//优先队列解决,广度优先
struct Persion
{
int x,y;
int times;
friend bool operator < (const Persion &a,const Persion &b)
{
return a.times>b.times; //">" 返回队列中较小的元素;"< " 则返回队列中较大的元素
}
};
//这样优先级排序为小的在top(可以理解为右面是top)
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//四个方向的操作
char map[N][N];
int visited[N][N];
int m,n;
int BFS(int x,int y)
{
priority_queue <Persion> q; //新建优先队列
Persion current,next;
memset(visited,0,sizeof(visited));
current.x=x,current.y=y,current.times=0;
visited[current.x][current.y]=1;//标记访问过了
q.push(current); //当前访问的入队
while(!q.empty())
{
current=q.top();
q.pop(); //
for(int i=0;i<4;i++)//对四个方向查找
{
next.x=current.x+dir[i][0];
next.y=current.y+dir[i][1];
if( next.x>=0&&next.x<n && next.y>=0&&next.y<m && map[next.x][next.y]!='#' && !visited[next.x][next.y])
{
if(map[next.x][next.y]=='a')
return current.times+1;
if(map[next.x][next.y]=='x')
next.times=current.times+2;
else
next.times=current.times+1;
visited[next.x][next.y]=1;
q.push(next);
}
}
}
return -1;
}
int main()
{
int i,j;
Persion angle;
while(cin>>n>>m&&(m||n))
{
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
cin>>map[i][j];
if(map[i][j]=='r')
angle.x=i,angle.y=j;
}
int times=BFS(angle.x,angle.y);
if(times==-1)
cout<<"Poor ANGEL has to stay in the prison all his life."<<endl;
else
cout<<times<<endl;
}
return 0;
}
最后
以上就是缥缈大树为你收集整理的杭电 rescue(经典广搜)(深搜广搜对比)的全部内容,希望文章能够帮你解决杭电 rescue(经典广搜)(深搜广搜对比)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复