• HDU-1429 胜利大逃亡(续)


    A - 胜利大逃亡(续)
    Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
    Submit Status

    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
     
     
     
     
     
    被这么一道题目卡得要死了。。。我不明白,用BFS模拟的时候到底出了什么问题。我手算的答案和我用算法模拟的过程应该一致,为什么样例输出为16,而我只输出14.
     
    两天之后终于想明白这个题目。。。其实输出14很好模拟,就一个小细节处理问题。。这次又跪在细节上,即在搜索四个方向的时候,每次都要从同一个点出发才行,我居然一个地方手贱把出发点的状态改了。。结果就影响了其余的点,难怪会莫名其妙出来14。细节 啊!!!!!
    下面的代码可以出结果。。但是会MLE。。我想剪枝优化,但是失败了。。得用其他方法重新敲一遍!
     
     
    我想说终于把这道题目A掉了,下午的时候拼命的想怎么剪枝,因为题目必须允许路径往返,因此如果不采取任何措施的话,队列必定会被庞大的但其实毫无用处的点挤爆。
     
     
    重点在于状态压缩这种算法!!!!!!
    所以网上的博客学到了这种状态压缩方法,由我的代码也可以看出来,在结构体里新定义了一个叫做hashnum的变量,用来跟相应的hashkey数组匹配使用,hashkey数组为什么这么定义也是有原因的因为总共有10把钥匙,就意味着任何时候到底手里有几把钥匙有2^10种,为了方便定义数组,就化成十进制,A钥匙代表1,B代表2,C代表4..J代表512;
    这样的话,得到任意的钥匙,我都能更新当前状态,通过b.hashnum+=对应字母的hashkey值。。。
    求出的b.hashnum主要还是为状态 nodestate服务的,及时更新当前访问了nodestate[x][y][hashnum]=1;下一次再访问到该状态,直接continue。
    为什么这个方法对这个题目有效呢
    想一下就知道,我的三维数组保存了当前坐标的状态,下一次访问这个点,如果钥匙量(hashnum)没变,即中间走的路完全没用,就滤过它。。。这样就达到了我需要减掉不必要的点。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    int dir[][2]= {{0,1},{0,-1},{1,0},{-1,0}};
    char map[30][30];
    int hashkey[]={1,2,4,8,16,32,64,128,256,512};
    bool nodestate[30][30][1024];
    int n,m,t;
    struct node
    {
        short x,y;
        bool key[11];
        short time;
        int hashnum;
    };
    int bfs(node star)
    {
        memset(nodestate,0,sizeof nodestate);
        queue<node> q;
        q.push(star);
        while (!q.empty())
        {
            node b=q.front();
            q.pop();
            int nx,ny;
            if (b.time>=t) return -1;
            if (map[b.x][b.y]=='^') return b.time;
            for (int i=0; i<4; i++)
            {
                nx=b.x+dir[i][0];
                ny=b.y+dir[i][1];
                if (nx<0||nx>=n||ny<0||ny>=m) continue;
                if (map[nx][ny]=='*') continue;
                if (nodestate[nx][ny][b.hashnum]==1) continue;//状态已经被访问过,所以这个点是废点,略过
                char ch=map[nx][ny];
    
                if (ch>='A'&&ch<='Z')
                {
                    int temp=ch-'A';
                    if (b.key[temp]==false)
                        continue;
                }
                if (ch>='a'&&ch<='z')
                {
                    int temp=ch-'a';
                    if (!b.key[temp])
                    {
                      if (!nodestate[nx][ny][b.hashnum+hashkey[temp]])//没有访问的状态,开始增加新点,并记录好该状态已被访问
                      {
                        node d=b;
                        d.x=nx;
                        d.y=ny;
                        d.time=b.time+1;
                        d.key[temp]=true;
                        d.hashnum+=hashkey[temp];
                        q.push(d);
                        nodestate[nx][ny][d.hashnum]=1;
                        continue;
                      }
                    }
    
                }
                nodestate[nx][ny][b.hashnum]=1;
                node c=b;
                c.x=nx;
                c.y=ny;
                c.time=b.time+1;
                q.push(c);
            }
        }
        return -1;
    }
    int main()
    {
        int sx,sy;
        while (scanf("%d%d%d",&n,&m,&t)!=EOF)
        {
            for (int i=0; i<n; i++)
            {
                for(int j=0; j<m; j++)
                {
                    cin>>map[i][j];
                    if (map[i][j]=='@')
                    {
                        sx=i;
                        sy=j;
                    }
                }
            }
            node start;
            start.x=sx;
            start.y=sy;
            start.hashnum=0;
            start.time=0;
            for (int k=0; k<11; k++)
            {
                start.key[k]=false;
            }
            int ans=bfs(start);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    使用RabbitMq
    创建.NET core的守护进程
    nginx配置
    让.net core 支持静态文件
    关于sql中如何动态加WHERE条件
    CentOS上部署.net core
    chrom中 background 调用pop.js
    windows下安装redis
    sql server导出大批量数据
    python爬虫笔记
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3205372.html
Copyright © 2020-2023  润新知