zoukankan      html  css  js  c++  java
  • hdu 1429 胜利大逃亡(续) (bfs+状态压缩)

    题目连接

    Problem Description
    Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……

    这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。

    Input
    每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:

    . 代表路
    * 代表墙
    @ 代表Ignatius的起始位置
    ^ 代表地牢的出口
    A-J 代表带锁的门,对应的钥匙分别为a-j
    a-j 代表钥匙,对应的门分别为A-J
    

    每组测试数据之间有一个空行。

    Output
    针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。

    Sample Input

    4 5 17
    @A.B.
    a*.*.
    *..*^
    c..b*
    
    4 5 16
    @A.B.
    a*.*.
    *..*^
    c..b*
     
    

    Sample Output
    16
    -1

    分析:
    虽然只是一个续,但是这怪物升级的有点快,打怪之路还是很艰辛啊。跟上一道提的难度完全不是一个等级的····

    言归正传,来看一下这道题

    因为有10中不同的钥匙,每种都有两种状态,所以结合计算机是二进制保存的特点,刚好把这10把钥匙当成每一个为,要要1<<10个位保存所有的状态,然后就是模拟捡起钥匙,捡起钥匙就是说明这个位上的数字变成1这个状态,所以自然而然想到了位运算,只要|一下就好了,然后改变在这个点的状态。。。。模拟碰到门的情况,那么就和这个位置上的位&一次,看是1还是0,1代表已经捡到了这把钥匙,可以开门。。这个样就变成了朴素的bfs了。。。

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<queue>
    #include<string.h>
    char map[25][25];
    bool vis[25][25][1<<11]; //2^11
    int flg[4][2]= {{1,0},{-1,0},{0,1},{0,-1} };
    int n,m,t,sx,sy;
    using namespace std;
    struct node
    {
        int x,y,step,key; //key 来储存当前钥匙
    } st;
    void bfs(int x,int y)
    {
        node Now,Next;
        Now.x=x;
        Now.y=y;
        Now.step=0;
        Now.key=0;
        queue<node>Q;
        Q.push(Now);
        while(!Q.empty())
        {
            Now=Q.front();
            //cout<<"now"<<now.x<<" "<<now.y<<" "<<now.step<<" "<<now.key<<endl;
            Q.pop();
            if(map[Now.x][Now.y]=='^')
            {
                if(Now.step<t)
                    printf("%d
    ",Now.step);
                else
                    printf("-1
    ");
                return ;
            }
            for(int i=0; i<4; i++)
            {
                Next.x=Now.x+flg[i][0];
                Next.y=Now.y+flg[i][1];
                Next.key=Now.key;
                Next.step=Now.step+1;
                if(Next.x<0||Next.x>=n||Next.y<0||Next.y>=m||map[Next.x][Next.y]=='*'||vis[Next.x][Next.y][Next.key])
                    continue;
                if(map[Next.x][Next.y]>='A'&&map[Next.x][Next.y]<='J')///如果走到的这个点是门
                {
                    if(Next.key&(1<<(map[Next.x][Next.y]-'A')))   //并且手里有钥匙
                    {
                        vis[Next.x][Next.y][Next.key]=1;
                        Q.push(Next);
                    }
                }
                else if(map[Next.x][Next.y]>='a'&&map[Next.x][Next.y]<='j')//走到的这个点是钥匙
                {
                    //如果没有钥匙
                    if((Next.key&(1<<(map[Next.x][Next.y]-'a')))==0)  //运算符优先级问题,,注意加括号
                    {
                        Next.key+=(1<<(map[Next.x][Next.y]-'a'));///手里拥有这把钥匙
                    }
                    vis[Next.x][Next.y][Next.key]=1;
                    Q.push(Next);
                }
                else
                {
                    vis[Next.x][Next.y][Next.key]=1;
                    Q.push(Next);
                }
            }
        }
        printf("-1
    ");
        return ;
    }
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&t))
        {
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                {
                    scanf(" %c",&map[i][j]);
                    if(map[i][j]=='@')///起始位置
                    {
                        sx=i;
                        sy=j;
                    }
                }
            memset(vis,0,sizeof(vis));
            bfs(sx,sy);
        }
        return 0;
    }
    
  • 相关阅读:
    cmd 一键获取 所有连接过的wifi 密码
    MYSQL注入语句
    Web安全篇之SQL注入攻击
    Kali Linux 不能联网上网 解决方法
    php杂项
    laravel下的数据序列化
    填充数据
    css
    array
    GD库常用函数
  • 原文地址:https://www.cnblogs.com/cmmdc/p/7611194.html
Copyright © 2011-2022 走看看