1002CDOJ(解救小Q)

做题感,就是很普通的写出了BFS,可是超时,在网上搜到这个高效的,很给力。简单搜索题,求最短路径,优先使用 BFS ,唯一需要注意的地方就是传送阵,传送阵联通的两点的深度一致。为了避免在搜索中寻找传送阵,我们可以在输入过程中,对传送阵两点进行关联。搜索过程中,若遇见传送阵,我们只需把与这一传送阵的另一端入队即可,而当前搜索遇到的这一端无需入队。
下面附上AC代码以及注释,希望能帮助到大家:
View Code
 1 #include<iostream>
 2  using namespace std;
 3 int vis[51][51],ans,n,m,dx[4]={-1,0,1,0},dy[5]={0,1,0,-1};
 4 struct trans
 5 {    int y,x;
 6 }a[2][30];
 7 struct node
 8 {    int c,d,step;
 9 }b[100000];
10 bool flag;char map[51][51];
11 void dfs(int x,int y,int step)
12 {
13     if(map[y][x]=='Q') {flag=true;ans=ans>step?step:ans;}
14     else
15     for(int i=0;i<4;i++)
16     {    int tx=x+dx[i],ty=y+dy[i],k1,k2;
17         if(tx>0&&tx<=m&&ty>0&&ty<=n&&map[ty][tx]!='#'&&vis[ty][tx]==0)
18         {    vis[ty][tx]=1;
19             if(map[ty][tx]>='a' && map[ty][tx]<='z')
20             {
21                 int k=map[ty][tx]-'a';
22                 if(a[0][k].y==ty && a[0][k].x==tx)      k1=a[1][k].y,k2=a[1][k].x;
23                 else      k1=a[0][k].y,k2=a[0][k].x;
24                 vis[k1][k2]=1;
25                 dfs(k2,k1,step+1);           
26                 vis[k1][k2]=0;
27             }
28             else
29             dfs(tx,ty,step+1);
30             vis[ty][tx]=0;
31         }
32     }
33 }
34 int main()
35 {    int T;
36     cin>>T;
37     while(T--)
38     {    cin>>n>>m;
39         flag=false;
40         int head=0,tail=1,vis1[30]={0};
41         ans=101;
42         for(int i=1;i<=n;i++)   
43         {
44             for(int j=1;j<=m;j++)
45             {    cin>>map[i][j];vis[i][j]=0;
46                 if(map[i][j]=='L')    map[i][j]='#',b[0].c=i,b[0].d=j;
47                 else if(map[i][j]>='a' && map[i][j]<='z')
48                 {    int k=map[i][j]-'a';
49                     if(vis1[k]==0)    a[0][k].y=i,a[0][k].x=j,vis1[k]=1;
50                     else a[1][k].y=i,a[1][k].x=j;
51                 }
52             }
53         }
54         b[0].step=0;
55         while(head<tail)
56         {    for(int i=0;i<4;i++)
57             {    int tx=b[head].d+dx[i],ty=b[head].c+dy[i],k1,k2;
58                 if(tx>0&&tx<=m&&ty>0&&ty<=n&&map[ty][tx]!='#'&&vis[ty][tx]==0)
59                 {    vis[ty][tx]=1;
60                     if(map[ty][tx]>='a' && map[ty][tx]<='z')
61                     {
62                         int k=map[ty][tx]-'a';
63                         if(a[0][k].y==ty && a[0][k].x==tx)      k1=a[1][k].y,k2=a[1][k].x;
64                         else      k1=a[0][k].y,k2=a[0][k].x;
65                         b[tail].c=k1,b[tail].d=k2;
66                         b[tail].step=b[head].step+1;tail+=1;                                   
67                     }
68                     else
69                     {    b[tail].c=ty,b[tail].d=tx;
70                         b[tail].step=b[head].step+1;
71                         if(map[ty][tx]=='Q') {flag=true;cout<<b[tail].step<<endl;}    tail+=1;
72                     }
73                 }
74             }
75             head+=1;
76         }
77         if(flag==false)    cout<<"-1"<<endl;
78     }
79 }
80              
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值