zoukankan      html  css  js  c++  java
  • HDU 1429 胜利大逃亡(续) (BFS+位压缩)

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

    胜利大逃亡(续)

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3309    Accepted Submission(s): 1063

    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
     
    Author
    LL
     
    Source
     
    Recommend
    linle
     
     
    这题很纠结。。。。想了好几天了。。。。一开始想到以每个点是否走过超过2次作为判断条件,调试的时候发现这种方法显然错误,后来又想到在结构体中加入存储钥匙的数组,可惜测试用例都过不了,后来想想,就算过了测试用例也应该会MLE的吧,貌似很复杂。。。。实在没办法了,只能找找题解了,看到有大牛介绍的位压缩方法。。。果断用上了,经过多次的WA后,终于A过。。。还得继续努力啊!加油!
     
    思路:
    用一个十位的二进制数表示钥匙,如00000000001代表有第一个钥匙,0000000010代表第二个钥匙。
    因为有10把钥匙,因此有2^10=1024种情况,可以用一个三维数组标记。
    如果该点为钥匙点,则可采用|运算来模拟拾取,显然0001 | 1000 = 1001
    当为相应的门时采用&运算来模拟开启,例如1101 & 0001 = 0001(即可以打开'A'门)
     
    Code
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<queue>
     4 #include<cstring>
     5 using namespace std;
     6 #define N 24
     7 struct node
     8 {
     9     int x;
    10     int y;
    11     int time;
    12     int key;
    13 };
    14 char g[N][N];
    15 int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
    16 int n,m,t,sx,sy,ex,ey;
    17 int vis[N][N][1030];
    18 void getd()
    19 {
    20     int i,j;
    21     char s[N];
    22     for(i=0;i<n;i++)
    23     {
    24         gets(s);
    25         for(j=0;j<strlen(s);j++)
    26         {
    27             g[i][j]=s[j];
    28             if(s[j]=='@')
    29             {
    30                 sx=i;//起点 
    31                 sy=j;
    32             }
    33             else if(s[j]=='^')
    34             {
    35                 ex=i;//终点 
    36                 ey=j;
    37             }
    38         }
    39     }
    40 }
    41 void bfs()
    42 {
    43     queue<node>q;
    44     memset(vis,0,sizeof(vis));
    45     node p,s;
    46     int i,j,key;
    47     p.x=sx;p.y=sy;
    48     p.time=p.key=0;
    49     vis[p.x][p.y][p.key]=1;
    50     q.push(p);
    51     while(!q.empty())
    52     {
    53         p=q.front();
    54         q.pop();
    55         for(i=0;i<4;i++)
    56         {
    57             s.x=p.x+dir[i][0];
    58             s.y=p.y+dir[i][1];
    59             s.key=p.key;
    60             s.time=p.time+1;
    61             if(!(s.x>=0&&s.x<n&&s.y>=0&&s.y<m)||g[s.x][s.y]=='*'||s.time>t)continue; 
    62             if(g[s.x][s.y]=='^'&&s.time<t){printf("%d\n",s.time);return ;}//已到达终点位置 
    63             if(g[s.x][s.y]>='a'&&g[s.x][s.y]<='z')
    64             {
    65                 key=1<<(g[s.x][s.y]-'a');
    66                 s.key|=key;//加入钥匙 
    67             }
    68             else if(g[s.x][s.y]>='A'&&g[s.x][s.y]<='Z')
    69             {
    70                 key=1<<(g[s.x][s.y]-'A');
    71                 if(!(key&s.key))continue;//没有钥匙,无法打开门 
    72             }
    73             if(vis[s.x][s.y][s.key])continue;//已经经历过该状态,不可再经历 
    74             vis[s.x][s.y][s.key]=1;//标记 
    75             q.push(s);
    76         }
    77     }
    78     printf("-1\n");
    79 }
    80 int main()
    81 {
    82     while(scanf("%d %d %d",&n,&m,&t)!=EOF)
    83     {
    84         getchar();
    85         getd();
    86         bfs();
    87     }
    88     return 0;
    89 }
  • 相关阅读:
    HDU 5791 Two (DP)
    POJ 1088 滑雪 (DPor记忆化搜索)
    LightOJ 1011
    POJ 1787 Charlie's Change (多重背包 带结果组成)
    HDU 5550 Game Rooms (ccpc2015 K)(dp)
    HDU 5542 The Battle of Chibi (ccpc 南阳 C)(DP 树状数组 离散化)
    HDU 5543 Pick The Sticks (01背包)
    HDU 5546 Ancient Go (ccpc2015南阳G)
    NB-IoT的DRX、eDRX、PSM三个模式 (转载,描述的简单易懂)
    MQTT 嵌入式端通讯协议解析(转)
  • 原文地址:https://www.cnblogs.com/lfeng/p/2999223.html
Copyright © 2011-2022 走看看