迷宫问题(bfs+队列)

迷宫问题:给出起点和终点,求解到最小步数或最小转向数

基本思路:bfs+队列优化,搜索在当前位置的状态的转移,是否到达过该状态则用vis标记,则一定能达到搜索结束的状态,复杂度是状态数

对bfs的理解:bfs可以理解为地毯式搜索,当从起点出发时,达到一步能到达的地方,在搜索两步能到达的地方,是一层一层分级的,假如是最小改变方向数的时候,即为改变一次方向能到达的地方,然后在搜索两步能到达的地方,如果状态并不是一步一步增大,就可能用的着优先队列,或者也可以加一个数组,表示新搜索的结果,是否小于当前答案,感觉用bfs来搜索迷宫问题,就像spfa最短路一样,优先确定第一步能达到的地方,再确定能用第一步松驰的结果来松弛的边,依次进行下去

对状态的理解:如hdu胜利大逃亡续中每当你处于某个位置时,你身上存在哪几把钥匙,当到达一扇门的时候,你是否能通过则通过钥匙来判断

1.hdu 1429 胜利大逃亡(续)

算法思路: 第一次想的状态是下x,y,key,lock.但后来发现lock的状态可不要,没必要特意去处理lock,因为x,y,已经确定了是否是锁,以及能不能通过;

     状态 vis[x][y][key]  钥匙的处理用状态压缩,另外注意状态是否合法,是否在地图中,是否访问过,是否超过时间

#include<bits/stdc++.h>
using namespace std;
int n,m,t,sx,sy,ex,ey,vis[21][21][(1<<11)];char mp[21][21];
int x_[4]={1,-1,0,0},y_[4]={0,0,1,-1};
struct node{
    int x,y,time,key;
};
bool inmp(int x,int y){
    if(x>=1&&x<=n&&y>=1&&y<=m&&mp[x][y]!='*') return true;
    else return false;
}
int bfs()
{
     queue<node> q;
     memset(vis, 0, sizeof(vis));
     node s,u,v;
     s.x = sx,s.y = sy,s.key = 0,s.time=0;
     vis[s.x][s.y][s.key] = 1;
     q.push(s);
    while(!q.empty())
    {
        u=q.front();q.pop();
        if(u.x==ex&&u.y==ey&&u.time<t) return u.time;
        for(int i=0;i<4;i++)
        {
            v.x=u.x+x_[i],v.y=u.y+y_[i],v.key=u.key;
            v.time=u.time+1;
            if(v.time>=t) continue;//时间小于1,退出 
            if(!inmp(v.x,v.y)) continue;//不在地图中退出 
            if(vis[v.x][v.y][v.key]) continue;
            char c=mp[v.x][v.y];
            if(c>='a'&&c<='j') {
                v.key|=(1<<(c-'a'));
                if(vis[v.x][v.y][v.key]) continue;
            }
            if(c>='A'&&c<='J'){
                if(!(v.key&(1<<(c-'A')))) continue;
             }
            vis[v.x][v.y][v.key]=1;
            q.push(v);
        }
    }
    return -1;
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        for (int i = 1; i <= n; i ++){
              getchar();
              for (int j = 1; j <= m; j ++){
              scanf("%c",&mp[i][j]);
              if (mp[i][j] == '@'){sx = i; sy = j;}
              if (mp[i][j] == '^'){ex = i; ey = j;}  
              }
        }
        int ans=bfs();
        printf("%d\n",ans);
    }
    return 0;
}
View Code

2.hdu 1254 推箱子

算法思路:状态 箱子的位置,人的位置,以及推箱子的步数,vis[x][y][x_][y_],如果人和箱子重合,则让推箱子,如果不能推动,则该状态不合法!!重中之重!!

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f; 
struct node{
    int x,y,x_,y_,step;
    friend bool operator <(node a,node b){
        return a.step>b.step;
    }
};
int t,n,m;int mp[10][10];int num[10][10][10][10];
int sx,sy,sx_,sy_,ex_,ey_,ans=INF;
int x_[4]={1,-1,0,0},y_[4]={0,0,-1,1};
bool inmp(int x,int y){
    if(x>=1&&x<=n&&y>=1&&y<=m&&mp[x][y]!=1) return true;
    else return false;
}
void bfs()
{
    queue<node>q;node s,u,v;ans=INF;
    memset(num,0x3f,sizeof(num));
    //cout<<num[0][0][0][0]<<endl;
    s.x=sx,s.x_=sx_,s.y=sy,s.y_=sy_,s.step=0;
    q.push(s);num[sx][sy][sx_][sy_]=0;
    while(!q.empty())
    {
        u=q.front();q.pop();
        //printf("%d %d %d %d %d\n",u.x,u.y,u.x_,u.y_,u.step);
        if(u.x_==ex_&&u.y_==ey_) ans=min(ans,u.step);
        for(int i=0;i<4;i++)
        {
            v=u;
            v.x+=x_[i],v.y+=y_[i];
            if(inmp(v.x,v.y)&&v.step<num[v.x][v.y][v.x_][v.y_])
            {
                if(v.x==v.x_&&v.y==v.y_)
                {
                    v.x_+=x_[i],v.y_+=y_[i];v.step++;
                    if(!inmp(v.x,v.y)||v.step>=num[v.x][v.y][v.x_][v.y_]) continue;
                    num[v.x][v.y][v.x_][v.y_]=v.step;
                    q.push(v);
                }
                else
                {
                    num[v.x][v.y][v.x_][v.y_]=v.step;
                    q.push(v);
                }
            }
        }
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&mp[i][j]);
            if(mp[i][j]==4) sx=i,sy=j;
            if(mp[i][j]==2) sx_=i,sy_=j;
            if(mp[i][j]==3) ex_=i,ey_=j;
        }
        bfs();
        //printf("%d %d %d %d %d %d\n",sx,sy,sx_,sy_,ex_,ey_);
        if(ans==INF) printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}
View Code

3.hdu 1728 逃离迷宫

算法思路:求最小转弯数,状态:位置+转弯次数 vis[x][y] 一旦被走过的位置一定是最小转弯数了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
    int x,y,t;
};
int n,m,sx,sy,ex,ey,k;char mp[101][101];int vis[101][101];
int x_[4]={1,-1,0,0},y_[4]={0,0,1,-1};
bool inmp(node a){
    if(a.x>=0&&a.x<n&&a.y>=0&&a.y<m&&mp[a.x][a.y]!='*') return true;
    else return false;
}
bool bfs()
{
    node s,u,v;queue<node>q;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            vis[i][j]=0; 
    s.x=sx,s.y=sy,s.t=-1;
    q.push(s);vis[sx][sy]=1;
    while(!q.empty())
    {
        u=q.front();q.pop();
        if(u.x==ex&&u.y==ey) return true;
        for(int i=0;i<4;i++)
        {
            v=u,v.t=u.t+1;if(v.t>k) break;
            while(1)//向一侧进行延伸 
            {
                v.x+=x_[i],v.y+=y_[i];
                if(!inmp(v)) break;
                if(v.x==ex&&v.y==ey) return true;    
                if(!vis[v.x][v.y]){ q.push(v);vis[v.x][v.y]=1;} 
            }
        }
    } 
    return false;
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    int t;cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                cin>>mp[i][j];
        cin>>k>>sy>>sx>>ey>>ex;
        sx--,sy--,ex--,ey--;
        if(bfs()) cout<<"yes"<<endl;
        else cout<<"no"<<endl;
    }
    return 0;
} 
View Code

4.hdu 1494 非常可乐

算法思路: 状态 :a,b,s的含量,以及最少倒的次数:vis[s][a] 因总含量一定,初始状态设为s,a,b三者的含量,末状态设为 s=s/2,a=s/2;转移方式有六种,即两者间互相倒满,细节讨论,搜索的力量无穷大啊,是真的暴力!

#include<bits/stdc++.h>
using namespace std;
struct node{
    int s,a,b,t;
};
int s,a,b,vis[110][110];
int bfs()
{
    node ss,u,v;queue<node>q;
    ss.a=0,ss.b=0,ss.s=s,ss.t=0;
    q.push(ss);vis[ss.a][ss.b]=1;
    while(!q.empty())  
    {  
        u=q.front();q.pop();  
        if(u.a==s/2 && u.s==s/2)  return u.t;  
        if(u.s && u.a!=a)   //s->a  
        {  
            int c=a-u.a;  
            if(u.s>=c) v.a=a,v.s=u.s-c;  
            else v.a=u.a+u.s,v.s=0;  
            v.b=u.b; v.t=u.t+1;  
            if(!vis[v.a][v.b]) 
            {  
                q.push(v);  
                vis[v.a][v.b]=1;  
            }  
        }  
        if(u.s && u.b!=b)   //s->b  
        {  
            int c=b-u.b;  
            if(u.s>=c) v.b=b,v.s=u.s-c;  
            else v.b=u.b+u.s,v.s=0;  
            v.a=u.a; v.t=u.t+1;  
            if(!vis[v.a][v.b])  
            {  
                q.push(v);  
                vis[v.a][v.b]=1;  
            }  
        }  
        if(u.a && u.s!=s)   //a->s  
        {  
            int c=s-u.s;  
            if(u.a>=c) v.s=s,v.a=u.a-c;  
            else v.s=u.s+u.a,v.a=0;  
            v.b=u.b; v.t=u.t+1;  
            if(!vis[v.a][v.b])  
            {  
                q.push(v);  
                vis[v.a][v.b]=1;  
            }  
        }  
        if(u.a && u.b!=b)   //a->b  
        {  
            int c=b-u.b;  
            if(u.a>=c) v.b=b,v.a=u.a-c;  
            else v.b=u.b+u.a,v.a=0;  
            v.s=u.s; v.t=u.t+1;  
            if(!vis[v.a][v.b])  
            {  
                q.push(v);  
                vis[v.a][v.b]=1;  
            }  
        }  
        if(u.b && u.a!=a)   //b->s  
        {  
            int c=a-u.a;  
            if(u.b>=c) v.a=a,v.b=u.b-c;  
            else v.a=u.a+u.b,v.b=0;  
            v.s=u.s; v.t=u.t+1;  
            if(!vis[v.a][v.b])  
            {  
                q.push(v);  
                vis[v.a][v.b]=1;  
            }  
        }  
        if(u.b && u.s!=s)   //b->a  
        {  
            int c=s-u.s;  
            if(u.b>=c) v.s=s,v.b=u.b-c;  
            else v.s=u.s+u.b,v.b=0;  
            v.a=u.a; v.t=u.t+1;  
            if(!vis[v.a][v.b])  
            {  
                q.push(v);  
                vis[v.a][v.b]=1;  
            }  
        }    
    }  
    return 0;   
}
int main()
{
    while(~scanf("%d%d%d",&s,&a,&b),a+b+s)
    {
        memset(vis,0,sizeof(vis)); 
        if(s&1) {printf("NO\n");continue;}
        if(a<b) swap(a,b);
        int ans=bfs();
        if(ans) printf("%d\n",ans);
        else printf("NO\n");
    }
    return 0;
}
View Code

5.hdu 1253 胜利大逃亡

算法思路 :三位迷宫 ,模板即可

#include<bits/stdc++.h>
using namespace std;
int a_,b_,c_,ti;
struct node{
    int x,y,z,t;
};
int mp[51][51][51];
int x_[6]={0,0,0,0,1,-1},y_[6]={0,0,1,-1,0,0},z_[6]={1,-1,0,0,0,0};
bool inmp(node a){
    if(a.x>=1&&a.x<=a_&&a.y>=1&&a.y<=b_&&a.z>=1&&a.z<=c_) return true;
    else return false;
}
int bfs()
{
    node s,tmp,nn;queue<node>q;
    s.x=1,s.y=1,s.z=1,s.t=0;
    q.push(s);mp[1][1][1]=1;
    while(!q.empty())
    {
        tmp=q.front();q.pop();
        if(tmp.t>ti) continue;
        if(tmp.x==a_&&tmp.y==b_&&tmp.z==c_) return tmp.t;
        for(int i=0;i<6;i++)
        {
            nn.x=tmp.x+x_[i];
            nn.y=tmp.y+y_[i];
            nn.z=tmp.z+z_[i];
            if(!inmp(nn)) continue;
            if(mp[nn.x][nn.y][nn.z]) continue;
            nn.t=tmp.t+1;
            mp[nn.x][nn.y][nn.z]=1;
            q.push(nn);
        }
    }
    return -1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d",&a_,&b_,&c_,&ti);
        for(int i=1;i<=a_;i++)
            for(int j=1;j<=b_;j++)
                for(int k=1;k<=c_;k++)
                    scanf("%d",&mp[i][j][k]);
        int ans=bfs();
        printf("%d\n",ans);
    }
    return 0;
}
View Code

6.hdu 1242 Rescue

算法思路:基础迷宫+优先队列,vis[x][y],因为杀死敌人会浪费时间,所以用优先队列保持bfs用时间的分层性

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
    int x,y,t;
    friend bool operator < (node a,node b){
        return a.t>b.t;
    }
};
int sx,sy,ex,ey,n,m;
char mp[210][210];bool vis[210][210];
int x_[4]={1,-1,0,0},y_[4]={0,0,1,-1};
bool inmp(node a){
    if(a.x>=1&&a.x<=n&&a.y>=1&&a.y<=m&&mp[a.x][a.y]!='#')
        return true;
    else return false;
}
int bfs()
{
    node s,u,v;priority_queue<node>q;
    memset(vis,0,sizeof(vis));
    s.x=sx,s.y=sy,s.t=0;q.push(s);vis[sx][sy]=true;
    while(!q.empty())
    {
        u=q.top();q.pop();
        //cout<<u.x<<' '<<u.y<<' '<<u.t<<endl;
        if(mp[u.x][u.y]=='r') return u.t;
        for(int i=0;i<4;i++)
        {
            v.x=u.x+x_[i],v.y=u.y+y_[i];
            if(!inmp(v)||vis[v.x][v.y]) continue;
            if(mp[v.x][v.y]=='x') v.t=u.t+2;
            else v.t=u.t+1;
            vis[v.x][v.y]=true;
            q.push(v);
        }
    }
    return 0;
}
int main()
{
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {    cin>>mp[i][j];
            if(mp[i][j]=='a')sx=i,sy=j;
        }
        int ans=bfs();
        if(ans) cout<<ans<<endl;
        else cout<<"Poor ANGEL has to stay in the prison all his life."<<endl;
    }
    return 0;
}
View Code

7.hdu 1181 变形课

算法思路:建图,迷宫模板题,或者计算最短路

#include<bits/stdc++.h>
using namespace std;
const int INF=1000;
const int n=25;
int mp[27][27],dis[27],vis[27];char str[100];
void spfa(int s)
{
    for(int i=0;i<n;i++)
        dis[i]=INF,vis[i]=0;
    queue<int>q;
    q.push(s);dis[s]=0;vis[s]=1;
    while(!q.empty())
    {
        int now=q.front();q.pop();vis[now]=0;
        for(int i=0;i<n;i++)
        {
            if(dis[i]>dis[now]+mp[now][i])
            {
                dis[i]=dis[now]+mp[now][i];
                if(!vis[i]){
                    vis[i]=1;
                    q.push(i);
                }
            }
        }
    }
    return;
}
void init()
{
    for(int i=0;i<26;i++)
        for(int j=0;j<26;j++)
            mp[i][j]=(i==j)?0:INF;
}
int main()
{
    init();
    while(~scanf("%s",&str))
    {    
        if(str[0]!='0')
        {
            int len=strlen(str);
            int a=str[0]-'a',b=str[len-1]-'a';
            mp[a][b]=1;
        }   
        else
        {
            int s='b'-'a',e='m'-'a';
            spfa(s);
            if(dis[e]<INF) printf("Yes.\n");
            else printf("No.\n");
            init();
        }
    }
    return 0;
}
View Code

8.hdu 1180 诡异的楼梯

算法思路:状态:坐标和时间,vis[x][y],同时由时间的奇偶性确定能否到达楼梯的对面,同时用优先队列进行分层,对题意的理解至关重要

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
    int x,y,t;
    friend bool operator < (node a,node b){
        return a.t>b.t;
    }
}; 
char mp[21][21];int num[21][21];
int n,m,sx,sy,ex,ey,ans;
int x_[4]={1,-1,0,0},y_[4]={0,0,1,-1};
bool inmp(node a){
    if(a.x>=1&&a.x<=n&&a.y>=1&&a.y<=m&&mp[a.x][a.y]!='*') return true;
    else return false;
}
/*5 5 
**..T 
**.*.
..|.. 
.*.*. 
S....*/
void bfs()
{
    node s,u,v;priority_queue<node>q;
    s.x=sx,s.y=sy,s.t=0;
    q.push(s);memset(num,0x3f,sizeof(num));
    while(!q.empty())
    {
        u=q.top();q.pop();
        //cout<<u.x<<' '<<u.y<<' '<<u.t<<endl;
        for(int i=0;i<4;i++)
        {
            v.x=u.x+x_[i],v.y=u.y+y_[i];
            if(!inmp(v)) continue;
            if(mp[v.x][v.y]=='|')
            {
                if((u.t%2==0&&i<=1)||(u.t%2&&i>=2))
                {
                    v.x+=x_[i],v.y+=y_[i];
                    v.t=u.t+1;
                    if(num[v.x][v.y]&&v.t<num[v.x][v.y]){
                        num[v.x][v.y]=v.t;
                        if(v.x==ex&&v.y==ey) {ans=v.t;return;}
                        q.push(v);
                    }
                }
                else
                {
                    v=u,v.t++;
                    if(v.x==ex&&v.y==ey) {ans=v.t;return;}
                    q.push(v);
                }
            }
            else if(mp[v.x][v.y]=='-')
            {
                if((u.t%2==0&&i>=2)||(u.t%2&&i<=1))
                {
                    v.x+=x_[i],v.y+=y_[i];
                    v.t=u.t+1;
                    if(num[v.x][v.y]&&v.t<num[v.x][v.y]){
                        num[v.x][v.y]=v.t;
                        if(v.x==ex&&v.y==ey) {ans=v.t;return;}
                        q.push(v);
                    }
                }
                else
                {
                    v=u,v.t++;
                    if(v.x==ex&&v.y==ey) {ans=v.t;return;}
                    q.push(v);
                }
            }
            else
            {
                v.t=u.t+1;
                if(num[v.x][v.y]&&v.t<num[v.x][v.y]){
                    num[v.x][v.y]=v.t;
                    if(v.x==ex&&v.y==ey) {ans=v.t;return;}
                    q.push(v);
                }
            }
            
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin>>mp[i][j];
            if(mp[i][j]=='S') sx=i,sy=j;
            if(mp[i][j]=='T') ex=i,ey=j;
        }
        bfs();
        cout<<ans<<endl; 
    }
    return 0;
}
View Code

9.hdu 1175 连连看

算法思路:最小方向数

#include<bits/stdc++.h>
using namespace std;
int mp[1010][1010],n,m,q_,ss[1010][1010];
int x_[4]={0,0,-1,1},y_[4]={1,-1,0,0};
struct node{
    int x,y,step,dir;
};
queue<node>q;
bool bfs(int x1,int y1,int x2,int y2)
{
    node s,p,t;while(!q.empty()) q.pop();
    s.x=x1,s.y=y1,s.dir=0,s.step=0;
    q.push(s);
    while(!q.empty())
    {
        p=q.front();q.pop();
        if(p.x==x2&&p.y==y2&&p.step<=2) return true; 
        for(int i=0;i<4;i++)
        {
            t.x=p.x+x_[i],t.y=p.y+y_[i];
            if(t.x<1||t.x>n||t.y<1||t.y>m) continue;
            t.dir=i+1,t.step=p.step;
            if(p.dir&&t.dir!=p.dir) t.step++;
            if(t.step>2) continue;
            if(!mp[t.x][t.y]||(t.x==x2&&t.y==y2))
                if(ss[t.x][t.y]>=t.step){
                    ss[t.x][t.y]=t.step;
                    q.push(t);
                }
        }
    }
    return false; 
}
int main()
{
    while(~scanf("%d%d",&n,&m),n+m)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&mp[i][j]);
        scanf("%d",&q_);
        int x1,y1,x2,y2;
        while(q_--)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if(mp[x1][y1]==0||mp[x2][y2]==0||mp[x1][y1]!=mp[x2][y2]||(x1==x2&&y1==y2))
            {printf("NO\n");continue;}
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    ss[i][j]=100;
            ss[x1][y1]=0;
            bool flag=bfs(x1,y1,x2,y2);
            if(flag) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
} 
View Code

10.hdu 1072 Nightmare

算法思路:状态:位置,和此时的剩余时间 vis[x][y][t] ,bfs+队列即可

#include<bits/stdc++.h>
using namespace std;
struct node{
    int x,y,t,step;
};
int x_[4]={1,-1,0,0},y_[4]={0,0,1,-1};
int n,m,t,sx,sy,ex,ey,mp[20][20];
bool used[20][20][7];queue<node>q;
int bfs()
{
    node s,p,t;queue<node>q;
    memset(used,0,sizeof(used));
    s.x=sx,s.y=sy,s.step=0,s.t=6;
    q.push(s);used[sx][sy][6]=true;
    while(!q.empty())
    {
        p=q.front();q.pop();
        if(p.x==ex&&p.y==ey&&p.t>=1) return p.step;
        for(int i=0;i<4;i++)
        {
            t.x=p.x+x_[i],t.y=p.y+y_[i];
            t.step=p.step+1,t.t=p.t-1; 
            if(t.x<1||t.x>n||t.y<1||t.y>m) continue;
            if(!mp[t.x][t.y])continue;
            if(t.t<1) continue;
            if(used[t.x][t.y][t.t]) continue;
            if(mp[t.x][t.y]==4){
                t.t=6;
                if(used[t.x][t.y][t.t]) continue;
            }
            used[t.x][t.y][t.t]=true;
            q.push(t);
        }
    }
    return -1;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&mp[i][j]);
            if(mp[i][j]==2) sx=i,sy=j;
            if(mp[i][j]==3) ex=i,ey=j;
        }
        int b=bfs();
        printf("%d\n",b);
    }
    return 0;
}
View Code

11.hdu 2612 Find a way

算法思路:跑两次bfs模板,合并取最小值即可

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
    int x,y,step;
};
int n,m,sx1,sx2,sy1,sy2,tmp;char mp[201][201];int ans1[201][201],ans2[201][201];
bool inmp(int x,int y){
    if(x>=1&&x<=n&&y>=1&&y<=m&&mp[x][y]!='#') return true;
    else return false;
}
int vis[201][201];
int x_[4]={1,-1,0,0},y_[4]={0,0,1,-1};
void bfs(int sx,int sy)
{
    if(sx==sx1) tmp=1;
    else tmp=0;
    if(tmp)memset(ans1,0x3f,sizeof(ans1));
    else  memset(ans2,0x3f,sizeof(ans2));
    memset(vis,0,sizeof(vis));
    queue<node>q;node s,u,v;
    s.x=sx,s.y=sy,s.step=0;
    q.push(s);vis[sx][sy]=1;
    while(!q.empty())
    {
        u=q.front();q.pop();
        if(mp[u.x][u.y]=='@') if(tmp) ans1[u.x][u.y]=u.step;else ans2[u.x][u.y]=u.step;
        for(int i=0;i<4;i++)
        {
            v.x=u.x+x_[i],v.y=u.y+y_[i],v.step=u.step+1;
            if(!inmp(v.x,v.y)||vis[v.x][v.y]) continue;
            vis[v.x][v.y]=1;
            q.push(v); 
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>mp[i][j];
                if(mp[i][j]=='M')sx1=i,sy1=j;
                if(mp[i][j]=='Y')sx2=i,sy2=j;
            }
        bfs(sx1,sy1);
        bfs(sx2,sy2);
        int ans_x=0,ans_y=0,ans=100000000;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='@')
                    ans=min(ans,ans1[i][j]+ans2[i][j]);
        cout<<ans*11<<endl; 
    }
    
    
    
}
View Code

 12.newcoder逃离迷宫

算法思路:bfs+状态:vis[x][y][2]  0代表无钥匙,1代表有钥匙

#include<bits/stdc++.h>
#include<queue> 
using namespace std; 
struct node{
    int x,y,v,t;
};
char mp[510][510];int n,m,s_x,s_y,e_x,e_y;
int x_[4]={1,0,-1,0},y_[4]={0,1,0,-1};
bool inmp(int x,int y){return x>=0&&x<n&&y>=0&&y<m;}
int vis[510][510][2];//0,1
int bfs(){
    queue<node>q;
    q.push({s_x,s_y,0,0});
    memset(vis,0,sizeof(vis));
    vis[s_x][s_y][0]=1;
    while(!q.empty()){
        node u=q.front();q.pop();
        //cout<<u.x<<" "<<u.y<<endl;
        if(u.x==e_x&&u.y==e_y&&u.v==1) return u.t;
        for(int i=0;i<4;i++){
            node vv=u;vv.x+=x_[i],vv.y+=y_[i];vv.t++;
            if(!inmp(vv.x,vv.y)) continue;
            if(mp[vv.x][vv.y]=='K') vv.v=1;
            if(vis[vv.x][vv.y][vv.v]) continue;
            vis[vv.x][vv.y][vv.v]=1;
            if(mp[vv.x][vv.y]=='#') continue;
            if(mp[vv.x][vv.y]=='E'&&vv.v==0) continue;
            q.push({vv.x,vv.y,vv.v,vv.t});
        }
    }
    return -1;
} 
int main(){
    int t;scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) scanf("%s",&mp[i]);
        for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            if(mp[i][j]=='P') s_x=i,s_y=j;
            if(mp[i][j]=='E') e_x=i,e_y=j;
        }
        int ans=bfs();
        if(ans==-1) printf("No solution\n");
        else printf("%d\n",ans);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/vainglory/p/8497206.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值