hdu(1429) 胜利大逃亡(续) 队列+bfs+状态压缩

本文深入探讨状态压缩技术在解决迷宫问题中的应用,通过使用位运算实现钥匙获取与门开启的模拟,展示了如何将抽象概念转化为实际编程解决方案。文章详细阐述了状态压缩的方法论,并通过实例代码演示了从理论到实现的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*本题用到状态压缩,这个还真没想到,想到了也不会。。
得好好学学状态压缩了;

本题要采用|运算来模拟拾取钥匙点;(用<<左移合并);
用&来判断是否能打开该门;        (>>右移&1来判断);

100表示有第3把,111表示有第3,2,1把钥匙,如果该点为钥匙点,则可采用|运算来模拟拾取,
显然0001|1000 = 1001,同理,当为相应的门时采用&运算来模拟开启,
例如1101 & 0001 = 0001(即可以打开'A'门)*/

 

#include"stdio.h"
#include"string.h"
#include"queue"
using namespace std;
char map[21][21];
int visit[21][21][1<<10];
int dir[4][2]={-1,0,  0,1,  1,0,  0,-1};
int n,m,k,sx,sy,ex,ey;
struct point
{
    int x,y,z;
    int step;
};
int judge(int x,int y)
{
    if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='*')
        return 1;
    return 0;
}
int bfs(int x,int y)
{
    int i,p;
    memset(visit,0,sizeof(visit));
    queue<point>q;
    point cur,next;
    cur.x=x;cur.y=y;cur.step=0;cur.z=0;
 visit[x][y][0]=1;
    q.push(cur);
    while(!q.empty())
    {
        next=q.front();
        q.pop();
  if(next.step>=k)
   return -1;
        if(next.x==ex&&next.y==ey&&next.step<k)
            return next.step;
        for(i=0;i<4;i++)
        {
            cur.x=x=next.x+dir[i][0];
            cur.y=y=next.y+dir[i][1];
   cur.step=next.step+1;
   cur.z=next.z;           
            if(judge(x,y))
            {
    if(map[x][y]>='a'&&map[x][y]<='j')
    {
     p=(1<<(map[x][y]-'a')); //<<左移运算符 ,例map[][]为'b',则左移1位,变10  ;
     cur.z=(cur.z|p);//把p放进去;
     if(visit[x][y][cur.z]==0)
     {
      visit[x][y][cur.z]=1;
      q.push(cur);
     }

    }
    else if(map[x][y]>='A'&&map[x][y]<='J')
                {
                  p=(cur.z>>(map[x][y]-'A'));//>>右移运算符 ,若next=1010,右移一位变为101,
                                             //101&1!=0即可以开门 
      if((p&1)&&!visit[x][y][cur.z])
      {
       visit[x][y][cur.z]=1;
                      q.push(cur);
                  }

                }
                else if(!visit[x][y][cur.z])
                {  
     visit[x][y][cur.z]=1;
                    q.push(cur);
                }
            }
        }
    }
    return -1;
}
int main()
{
    int i,j;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        for(i=0;i<n;i++)
        {
            scanf("%s",map[i]);
                for(j=0;j<m;j++)
                {
                    if(map[i][j]=='@')
                    {
                        sx=i;sy=j;
                    }
                    if(map[i][j]=='^')
                    {
                        ex=i;ey=j;
                    }
                }
        }
        printf("%d\n",bfs(sx,sy));
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值