bfs

1.题意就是给一个图,里面有钥匙和门,一把钥匙对应一种门,问能不能到终点,如果不能输出-1,如果能输出最小步数。

直接队列bfs,注意拿了不同钥匙的状态是不一样的,是可以接着走下去的,注意判断什么时候算重复状态就行。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
struct ttt{
    int r,c;
    bool a[5];
    int step;
};
int dr[4]={0,1,-1,0};
int dc[4]={1,0,0,-1};
char map1[1005][1005];
bool walk[1005][1005][2][2][2][2];
ttt s1,s2;
int main(){
    //freopen("in.txt","r",stdin);
    int i,j,k,l1,l2,l3,f1,f2,f3,t1,t2,t3;
    int n,m;
    int r,c;
    while(scanf("%d%d",&r,&c)==2){
    memset(walk,0,sizeof(walk));
    //memset(s1,0,sizeof(s1));
    memset(s1.a,0,sizeof(s1.a));
    s1.step=0;
    for(i=1;i<=r;i++)
    for(j=1;j<=c;j++){
        cin >> map1[i][j];
        if(map1[i][j]=='0'){
          s1.r=i;
          s1.c=j;
        }
        if(map1[i][j]=='#'){
            s2.r=i;
            s2.c=j;
        }
}
    /*for(i=1;i<=r;i++){
        for(j=1;j<=c;j++)
            cout << map1[i][j];
        cout << endl;
    }*/
   // cout <<s1 .r << s1.c << " " << s2.r << s2.c << endl;
    s1.step=0;
    queue<ttt>qq;
    qq.push(s1);
    walk[s1.r][s1.c][s1.a[0]][s1.a[1]][s1.a[2]][s1.a[3]]=1;
    ttt s3;
    while(!qq.empty()){
        s1=qq.front();qq.pop();
        //cout << s1.r <<" "  << s1.c << "  " <<s1.step <<endl;
        if(s1.r==s2.r&&s1.c==s2.c)break;
        for(i=0;i<4;i++){
        s3.r=s1.r+dr[i];
        s3.c=s1.c+dc[i];
        s3.a[4]=s1.a[4];
        s3.a[1]=s1.a[1];
        s3.a[2]=s1.a[2];
        s3.a[3]=s1.a[3];
        s3.step=s1.step+1;
      //1、看路径是否完全正确,然后检查代码
      //  cout << s3.r << " --- " << s3.c << " " << walk[s3.r][s3.c][s3.a[1]][s3.a[2]][s3.a[3]][s3.a[4]]
       // <<"  " << s3.a[1] << " " <<s3.a[2] <<" " <<s3.a[3]<<" " << s3.a[4]<<endl;
        if(map1[s3.r][s3.c]!='*'&&s3.r>=1&&s3.r<=r&&s3.c>=1&&s3.c<=c&&
           walk[s3.r][s3.c][s3.a[1]][s3.a[2]][s3.a[3]][s3.a[4]]==0){
                 walk[s3.r][s3.c][s3.a[1]][s3.a[2]][s3.a[3]][s3.a[4]]=1;
         //      cout << "进来" <<endl;
            if(map1[s3.r][s3.c]=='#'){
                qq.push(s3);
            }
            if(map1[s3.r][s3.c]=='1'){
            if(s3.a[1]==1)
                qq.push(s3);
            }else if(map1[s3.r][s3.c]=='2'){
            if(s3.a[2]==1)
                qq.push(s3);
            }else if(map1[s3.r][s3.c]=='3'){
            if(s3.a[3]==1)
                qq.push(s3);
            }else if(map1[s3.r][s3.c]=='4'){
            if(s3.a[4]==1)
                qq.push(s3);
            }
            // cout << map1[s3.r][s3.c] <<endl;
             if(map1[s3.r][s3.c]=='.'){
       //     cout << "进去" << endl;
                qq.push(s3);
             }
             if(map1[s3.r][s3.c]=='0'){
                qq.push(s3);
            }else if(map1[s3.r][s3.c]=='5'){
                s3.a[1]=1;
                qq.push(s3);
            }else if(map1[s3.r][s3.c]=='6'){
                s3.a[2]=1;
                qq.push(s3);
            }else if(map1[s3.r][s3.c]=='7'){
                s3.a[3]=1;
                qq.push(s3);
            }else if(map1[s3.r][s3.c]=='8'){
                s3.a[4]=1;
                qq.push(s3);
        }
        }
    }
    }
    if(s1.r==s2.r&&s1.c==s2.c)
        cout << s1.step <<endl;
    else
        cout <<"-1"<<endl;
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值