码迷,mamicode.com
首页 > 其他好文 > 详细

bfs+位运算 hdu 5094 有钥匙的迷宫

时间:2015-05-18 14:17:29      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:

题意:给你一个n*m的矩阵,每个格子可以移动到他上下左右四个格子.现在有些格子之间有门或墙.墙不能通过,每个门需要对应的钥匙打开.最多10种门,钥匙分布在某些格子上,走到这些格子上就能拿到钥匙.现在要从(1,1)走到(n,m)问最少要走多少步.如果不能到达输出-1.

样例解释:

4 49

9

1 2 1 3 2

1 2 2 2 0

2 1 2 2 0

2 1 3 1 0

2 3 3 3 0

2 4 3 4 1

3 2 3 3 0

3 3 4 3 0

4 3 4 4 0

2

2 1 2

4 2 1

有4*4的矩阵.其中有9个门或者墙:(1,2),(1,3)之间有门2.(1,2),(2,2)间是墙.....有两把钥匙:(2,1)上有钥匙2.(4,2)上有钥匙1.

 

解法:bfs基础上加 位运算.用一个数字记录当前拥有钥匙的情况.如:0000000011 (3)代表拥有钥匙1和2.然后判断点u到点v是否可以走.

代码:

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int n,m,p;
int g[3000][3000];
int ans=INF;
int dis[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int keylocal[800];
int vis[3000][1050];
struct node
{
    int step,num;
    int keys;
};
struct dian{
    int x,y;
}nod[3000];
bool haskey(int u,int v,node now)
{
    if(g[u][v]==-1){
        return true;
    }
    else{
        int key=now.keys;
        int doors=g[u][v];
        key>>=(doors-1);
        if(!(key & 1)){
            return false;
        }
        return true;
    }
}
void bfs()
{
    memset(vis,0,sizeof(vis));
    queue<node> que;
    node now;
    now.keys=0;
    if(keylocal[1]){
        int s=keylocal[1];
        int count=1;
           while(s){
                if(s&1){
                    int w=now.keys>>(count-1);
                    if(!(w&1)){
                        now.keys=now.keys+(1<<(count-1));
                    }
                }
                s=s>>1;
                count++;
           }
    }
    now.num=1,now.step=0;
    que.push(now);
    while(!que.empty()){
        node now=que.front();
        que.pop();
        int u=now.num;
        if(u==n*m){
            ans=now.step;
            return ;
        }
        for(int i=0;i<4;i++){
            int dx=nod[now.num].x+dis[i][0];
            int dy=nod[now.num].y+dis[i][1];
            int v=(dx-1)*m+dy;
            if(dx>=1 && dx<=n && dy>=1 && dy<=m && g[u][v]!=0 && haskey(u,v,now)&& !vis[v][now.keys]){
                vis[v][now.keys]=1;
                node next;
                next.num=v;
                next.step=now.step+1;
                next.keys=now.keys;
                if(keylocal[v]){
                    int s=keylocal[v];
                    //cout<<"s "<<s<<endl;
                    int count=1;

                   while(s){
                        if((s & 1)){
                            int w=next.keys>>(count-1);
                            if(!(w&1)){
                                    next.keys=next.keys+(1<<(count-1));
                            }
                            //cout<<"key "<<next.keys<<endl;
                            //cout<<"keys "<<s<<endl;
                        }
                        s=s>>1;
                        count++;
                   }
                }
                que.push(next);
            }
        }
    }
}
void make()
{
    int cnt=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            nod[cnt].x=i;
            nod[cnt++].y=j;
        }
    }
    for(int i=1;i<=n*m;i++){
        for(int j=0;j<4;j++){
            int dx=nod[i].x+dis[j][0];
            int dy=nod[i].y+dis[j][1];
            int v=(dx-1)*m+dy;
            if(dx>=1 && dx<=n && dy>=1 && dy<=m){
                g[i][v]=-1;
                g[v][i]=-1;
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&p)){
        ans=INF;
        int k;
        memset(g,0,sizeof(g));
        memset(keylocal,0,sizeof(keylocal));
        scanf("%d",&k);
        make();
        for(int i=0;i<k;i++){
            int x1,y1,x2,y2,w;
            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&w);
            int u=(x1-1)*m+y1;
            int v=(x2-1)*m+y2;
            if(g[u][v]==-1){
                g[u][v]=w;
            }
            else if(g[u][v]==0){
                g[u][v]=0;
            }
            g[v][u]=g[u][v];
        }
        int key;
        scanf("%d",&key);
        for(int i=0;i<key;i++){
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            int s=keylocal[(x-1)*m+y]>>(w-1);
            if(!(s&1)){
                keylocal[(x-1)*m+y]+=(1<<(w-1));
            }
        }
        bfs();
        if(ans>=INF){
            printf("-1\n");
        }
        else{
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

bfs+位运算 hdu 5094 有钥匙的迷宫

标签:

原文地址:http://www.cnblogs.com/Scale-the-heights/p/4511652.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!