题意:
Angel被传说中神秘的邪恶的Moligpy人抓住了!他被关在一个迷宫中。迷宫的长、宽不超过200。 迷宫中有不可以越过的墙以及监狱的看守。
Angel的朋友带了一些救援队来到了迷宫中。他们的任务是:接近Angel。我们假设接近Angel就是到达Angel所在的位置。
假设移动需要1单位时间,杀死一个看守也需要1单位时间。到达一个格子以后,如果该格子有看守,则一定要杀死。交给你的任务是,最少要多少单位时间,才能到达Angel所在的地方?(只能向上、下、左、右4个方向移动)
这个题是个很好的搜索题,有一个坑就是一定要从天使开始搜索盆友,因为盆友的数量不定的,我们找的是离天使最近的那个盆友,但是以前不知道的时候从天使搜索竟然没错!数据太水了!
还有一点需要注意的是遇到警卫时时间要加二,如果还是用普通队列就要注意了,不处理的话求出来的一定不是最小时间,所以第一次遇到标记一下,第二次如果碰到标记,时间再加一,不再往4面搜索!但是用优先队列就不用管那么多了,遇到警卫就加二就行了
所以这个题两种解法:
1:优先队列
2:普通队列+特殊处理
下面给出代码!
1:优先队列
#include
#include
#include
#include
using namespace std;
char map[210][210];
int vis[210][210],mov[4][2]={0,1,0,-1,1,0,-1,0};
int m,n;
struct node
{
int x,y,step;
friend bool operator <(node x,node y)//重载布尔,定义优先队列按步数从小到大排序
{
return x.step>y.step;
}
}now,nex;
bool can(node x)//检查当前点是否可以走
{
if(x.x<0||x.y<0||x.x>m-1||x.y>n-1||vis[x.x][x.y]||map[x.x][x.y]=='#')
return false;
return true;
}
int bfs(int x,int y)
{
priority_queueq;
now.x=x;
now.y=y;
now.step=0;
q.push(now);//将起点入队列
while(!q.empty())
{
now=q.top();
q.pop();
if(map[now.x][now.y]=='r')//找到朋友就直接函数结束,找到结果
return now.step;
for(int i=0;i<4;i++)
{
nex.x=now.x+mov[i][0];
nex.y=now.y+mov[i][1];
if(can(nex))
{
if(map[nex.x][nex.y]=='x')
nex.step=now.step+2;//如果当前点可以走,且此点为警卫,步数加二
else
nex.step=now.step+1;//如果当前点可以走,步数加一
vis[nex.x][nex.y]=1;
q.push(nex);//将此点入队列
}
}
}
return -1;
}
int main()
{
int i,j,sx,sy;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=0;i
#include
#include
#include
#include
using namespace std;
char map[210][210];
int vis[210][210],mov[4][2]={1,0,-1,0,0,1,0,-1};
int m,n;
struct node
{
int x,y,step,flag;
}now,nex;
bool can(node x)//检查当前点是否可以走
{
if(vis[x.x][x.y]||x.x<0||x.x>m-1||x.y<0||x.y>n-1||map[x.x][x.y]=='#')
return false;
return true;
}
int bfs(int a,int b)
{
int i;
queue q;
now.x=a;
now.y=b;
now.step=0;
now.flag=0;
q.push(now);//将起点入队列
while(!q.empty())
{
now=q.front();
q.pop();
if(now.flag)//第二次遇见警卫步数加一,重新标记flag=0
{
now.step++;
now.flag=0;
q.push(now);//这里一定要重新放回队列里
continue;
}
if(map[now.x][now.y]=='r')//找到朋友就直接函数结束,找到结果
return now.step;
for(i=0;i<4;i++)
{
nex.x=now.x+mov[i][0];
nex.y=now.y+mov[i][1];
if(can(nex))
{
nex.step=now.step+1;//如果当前点可以走,步数加一
if(map[nex.x][nex.y]=='x')
nex.flag=1;
else
nex.flag=0;//第一次遇见警卫,标记走过,且flag标记为 1
vis[nex.x][nex.y]=1;
q.push(nex);//将此点入队列
}
}
}
return -1;//如果没找到就返回-1
}
int main()
{
int i,j,sx,sy;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=0;i