hdu1429 胜利大逃亡(续) (BFS+简单状态压缩)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429

题目大意:逃离迷宫,但是迷宫里有钥匙和门

题目思路:

关于状态压缩:

 1.判断一个数字x二进制下第i位是不是等于1。

方法:if ( ( ( 1 << ( i - 1 ) ) & x ) > 0)

将1左移i-1位,相当于制造了一个只有第i位上是1,其他位上都是0的二进制数。然后与x做与运算,如果结果>0,说明x第i位 上是1,反之则是0。

2.将一个数字x二进制下第i位更改成1。

方法:x = x | ( 1<<(i-1) )

证明方法与1类似,此处不再重复证明。

3.把一个数字二进制下最靠右的第一个1去掉。

方法:x=x&(x-1)

题目:

因为一共只有十把钥匙,所以含有的状态较小,故可以使用状态压缩的方法储存是否拿到钥匙,那么visit数组就变成了 visit[x][y][状态],状态用二进制来表示,然后再用bfs进行处理就能较快速的完成这个问题。

代码:


#include <bits/stdc++.h>
using namespace std;
int n,m,t;
char mmap[21][21];
bool visit[21][21][2049];
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int sx,sy,ex,ey;
struct node
{
    int x,y,s;//s表示状态
    int step;
};
queue<node>Q;

int bfs()
{
    while(!Q.empty()) Q.pop();
    memset(visit,0,sizeof(visit));
    node a,now,next;
    a.x=sx,a.y=sy,a.s=0,a.step=0;
    visit[a.x][a.y][0]=1;
    Q.push(a);
    while(!Q.empty()){
        now = Q.front(),Q.pop();
        for(int i=0;i<4;i++){
            next.x=now.x+dir[i][0];
            next.y=now.y+dir[i][1];
            next.s=now.s;
            next.step=now.step+1;

            if(next.x==ex&&next.y==ey) return next.step;
            if(next.x<0||next.x>=n||next.y<0||next.y>=m) continue;
            if(mmap[next.x][next.y]=='*') continue;
            if(visit[next.x][next.y][next.s]) continue;
            if(mmap[next.x][next.y]>='A'&&mmap[next.x][next.y]<='Z'){
                int key=mmap[next.x][next.y]-'A'+1;
                if((next.s>>(key-1))&1){
                        Q.push(next);
                        visit[next.x][next.y][next.s]=1;
                }
                else continue;
            }
            if(mmap[next.x][next.y]>='a'&&mmap[next.x][next.y]<='z'){
                int nkey=mmap[next.x][next.y]-'a'+1;
                next.s=(next.s|(1<<(nkey-1)));
                if(!visit[next.x][next.y][next.s]){
                    visit[next.x][next.y][next.s]=1;
                    Q.push(next);
                }
                else continue;
            }
            if(mmap[next.x][next.y]=='.'){
                if(!visit[next.x][next.y][next.s]){
                    visit[next.x][next.y][next.s]=1;
                    Q.push(next);
                }
                else continue;
            }
            if(mmap[next.x][next.y]=='@'){
                if(!visit[next.x][next.y][next.s]){
                    visit[next.x][next.y][next.s]=1;
                    Q.push(next);
                }
                else continue;
            }
        }
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d%d",&n,&m,&t)){
        for(int i=0;i<n;i++){
            getchar();
            for(int j=0;j<m;j++){
            scanf("%c",&mmap[i][j]);
            if(mmap[i][j]=='@') sx=i,sy=j;
            if(mmap[i][j]=='^') ex=i,ey=j;
            }
        }

        printf("%d\n",bfs()<t?bfs():-1);
        getchar();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值