【BFS+优先队列】Battle City(poj-2312)



原题链接:点击打开链接

其实现在仔细想想,对初学者而言,在BFS和DFS中,还真是BFS学起来更为容易(至少我是这么认为)。BFS不需要层层递归,不需要考虑搜索路径不符合条件时应该如何变换。它只是一步一步的扫描,然后把相关信息归纳一下而已。我们需要的知识少许的STL知识就行了。

言归正传,这道题应该属于迷宫搜索题,而在搜索过程中,又要找出最少“消耗”的那一条路,从这点看,又有点像图论中的最短路了。因为需要记录消耗,而且需要选择路径,因此,不能用常规BFS中的队列来操作。

因此,建立一个表示坦克状态的结构体,其中包含位置下标i,j,以及从起始位置Y移动到当前位置的消耗cost;

然后,将搜索时的队列改为优先级队列。将消耗更小的设置为高优先级,如:

bool operator < (const place &a,const place &b)
{
       return a.cost>b.cost?true:false;
}


这样,每次在队列中的cost表示起点到当前点的消耗,按照消耗小的先出队的次序,当出队的坐标只想目标T时,完成搜索,同时返回“消耗”的值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=302;
char map[maxn][maxn];
bool visit[maxn][maxn];
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
struct place
{
       int cost,i,j;
};

bool operator < (const place &a,const place &b)//由于在优先队列中,按照cost的大小排序,队头为最优先
{
       return a.cost>b.cost?true:false;
}

bool BFS(int si,int sj)
{
       place in,out;
       priority_queue<place>que;//优先队列que
       in.i=si;
       in.j=sj;
       in.cost=0;
       visit[si][sj]=true;//访问起点
       que.push(in);//将起点存入队列
       while(!que.empty())//队列非空时持续进行
       {
              out=que.top();//访问队列中最优先点
              que.pop();//删除已访问的点
              if(map[out.i][out.j]=='T')//如果搜索目的达到,退出函数,返回真值
              {
                     printf("%d\n",out.cost);
                     return true;
              }
              for(int i=0;i<4;i++)
              {
                     in.i=out.i+dir[i][0];
                     in.j=out.j+dir[i][1];
                     char temp=map[in.i][in.j];
                     if(in.i<1||in.j<1||temp=='.'||temp=='S'||temp=='R'||visit[in.i][in.j])//设定入队要求
                            continue;
                     visit[in.i][in.j]=true;
                     in.cost=out.cost+1;
                     if(temp=='B')//如果经B点,cost+1
                            in.cost++;
                     que.push(in);//将符合条件的点入队
              }
       }
       return false;
}
int main()
{
       int n,m;
       while(scanf("%d%d",&m,&n)!=EOF&&(m||n))
       {
              int si,sj;
              memset(map,'.',sizeof(map));
              memset(visit,0,sizeof(visit));
              for(int i=1;i<=m;i++)
                     for(int j=1;j<=n;j++)
                     {
                            cin>>map[i][j];
                            if(map[i][j]=='Y')
                            {
                                   si=i;
                                   sj=j;
                            }
                     }
              if(!BFS(si,sj))
                     printf("-1\n");
       }
       return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值