hdu 1429 胜利大逃亡(续)

广搜+位运算:
在这里我们建立一个2进制钥匙串,如果对应位有钥匙则该位为1,反之为0,每当遇见钥匙,我们就把这把这把钥匙加到钥匙串的对应位置,广搜压栈的时候需要判断该位置是否为门的位置,并且检查是否有相应的钥匙,并且每个点对应一个钥匙串的状态,建立三维数组,前两位表示保存点的位置,后一位表示相应位置对应的钥匙的状态,进行一遍bfs即可。



#include<stdio.h>
int m,n,t;
char map[21][21];
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int find[21][21][1025];
int f[10000],a[10000],b[10000],bsu[10000];
int start_x,start_y,end_x,end_y;

int bfs(int x,int y)
{
    a[1]=x;
    b[1]=y;
    f[1]=0; 
    bsu[1]=0;
    int front=1;
    int rear=1;
    find[x][y][0]=1;
    while(front<=rear)
    {
        for(int i=0;i<4;i++)
        {
            int j,k;
            int xx=a[front]+dir_x[i];
            int yy=b[front]+dir_y[i];
            if('a'<=map[xx][yy]&&map[xx][yy]<='j')
            {
               if((f[front]>>(map[xx][yy]-'a'))%2==0) //把钥匙放到钥匙串的对应位置
                  j=f[front]^(1<<(map[xx][yy]-'a')) ; 
               else
                  j=f[front];
            } 
            else
                  j=f[front];
            if('A'<=map[xx][yy]&&map[xx][yy]<='J')
            {
                if((f[front]>>(map[xx][yy]-'A'))%2==1) //检查当前钥匙串中是否存在一把钥匙能把这把锁打开
                   k=1;
                else
                   k=0;
            } 
            else
                k=1;
            if(1<=xx&&xx<=m&&1<=yy&&yy<=n&&map[xx][yy]!='*'&&k==1)
              if(find[xx][yy][1024]==0||(find[xx][yy][1024]==1&&find[xx][yy][j]==0))
              {
                 rear++;
                 bsu[rear]=bsu[front]+1;
                 if(bsu[rear]>=t) return -1;
                 if(xx==end_x&&yy==end_y) return bsu[rear];
                 a[rear]=xx;
                 b[rear]=yy;
                 find[xx][yy][1024]=1;
                 find[xx][yy][j]=1;
                 f[rear]=j;
              }
        }
        front++;
      }
      return -1;
}
                          
int main()
{
   while(scanf("%d%d%d",&m,&n,&t)!=EOF)
   {
      getchar();
      for(int i=1;i<=m;i++)
      {
        for(int j=1;j<=n;j++)
        {
           scanf("%c",&map[i][j]);
           find[i][j][1024]=0;
           if(map[i][j]=='@')
           {
              start_x=i;
              start_y=j;
           }
           if(map[i][j]=='^')
           {
              end_x=i;
              end_y=j;
           }
           for(int k=0;k<=1023;k++)
             find[i][j][k]=0;
        }
        getchar();
      }
      printf("%d\n",bfs(start_x,start_y));
   }
   return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值