HDU 3085 Nightmare Ⅱ[双向广搜]

本文介绍了一种使用双向广度优先搜索算法解决迷宫问题的方法,通过从起点和终点同时搜索,优化搜索路径。文章详细阐述了算法实现过程,包括如何判断是否已走过格子、使用曼哈顿距离判断位置以及具体实现代码。

  很明显的双向广搜,每次从M的方向搜3步,从G的方向搜1步,然后判断是否走到对方已经走过的格子即可。至于魔王的判断,直接用曼哈顿距离判断就可以了。

  

 1 #include <string.h>
 2 #include <stdio.h>
 3 #include <queue>
 4 #include <stdlib.h>
 5 #define MAXN 805
 6 struct pnt{
 7     int x,y;
 8     pnt(){};
 9     pnt(int _x,int _y):x(_x),y(_y){}
10 }gst[2],st,en,q[2][MAXN*MAXN];
11 int front[2],rear[2];
12 int dx[4]={1,0,0,-1},dy[4]={0,1,-1,0};
13 int cas,n,m,sp[2],step,gsts;
14 char mz[MAXN][MAXN];
15 //判断是否已经是ghost的地盘,直接用曼哈顿距离判就可以了
16 int hasgst(int x,int y,int tm){
17     for(int i=0;i<2;i++)if(abs(x-gst[i].x)+abs(y-gst[i].y)<=tm*2)return 1;
18     return 0;
19 }
20 int bfs(int cur,int st,char now,char op){
21     for(int k=0;k<st;k++){
22         int ost=0,nst=0;
23         while(ost++<sp[cur]){
24             pnt p=q[cur][front[cur]++];
25             if(hasgst(p.x,p.y,step))continue;
26             for(int i=0;i<4;i++){
27                 int nx=p.x+dx[i],ny=p.y+dy[i];
28                 if(mz[nx][ny]=='X'||mz[nx][ny]==now||hasgst(nx,ny,step))continue;
29                 if(mz[nx][ny]==op)return 1;
30                 mz[nx][ny]=now;
31                 q[cur][rear[cur]++]=pnt(nx,ny);
32                 nst++;
33             }
34         }
35         sp[cur]=nst;
36     }
37     return 0;
38 }
39 //双广,M走3步,G走1步
40 int db_bfs(){
41     q[0][front[0]=rear[0]=0]=st,rear[0]++;
42     q[1][front[1]=rear[1]=0]=en,rear[1]++;
43     sp[0]=sp[1]=1,step=0;
44     while(front[0]<rear[0]&&front[1]<rear[1])
45         if(step++,bfs(1,1,'G','M')||bfs(0,3,'M','G'))return step;
46     return -1;
47 }
48 int main(){
49     scanf("%d",&cas);
50     while(cas--){
51         scanf("%d%d",&n,&m);
52         gsts=0;
53         for(int i=1;i<=n;i++){
54             scanf("%s",mz[i]+1);
55             for(int j=1;j<=m;j++){
56                 if(mz[i][j]=='Z')gst[gsts++]=pnt(i,j);
57                 else if(mz[i][j]=='M')st=pnt(i,j);
58                 else if(mz[i][j]=='G')en=pnt(i,j);
59             }
60         }
61         for(int i=0;i<=n;i++)mz[i][0]=mz[i][m+1]='X';
62         for(int i=0;i<=m;i++)mz[0][i]=mz[n+1][i]='X';
63         printf("%d\n",db_bfs());
64     }
65     return 0;
66 }

转载于:https://www.cnblogs.com/swm8023/archive/2012/08/28/2659817.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值