• 胜利大逃亡(续)


    胜利大逃亡(续)

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


    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
     
    View Code
      1 #include<iostream>
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<queue>
      5 using namespace std;
      6 int dir[][2]={{1,0},{0,1},{-1,0},{0,-1}};
      7 struct node
      8 {
      9     int x,y;
     10     int cnt;
     11     int time;
     12 };
     13 char map[22][22];
     14 int flag[2048][22][22];
     15 int x1,y1;
     16 int row,col,t;
     17 queue<node>q;
     18 
     19 bool judge(node tp)
     20 {
     21     if(tp.x<0 || tp.x>=row || tp.y<0 || tp.y>=col || map[tp.x][tp.y]=='*')
     22         return false;
     23     return true;
     24 }
     25 
     26 int bfs()
     27 {
     28     while(!q.empty())
     29         q.pop();
     30     node temp,p;
     31     int i,cc;
     32     p.x=x1;
     33     p.y=y1;
     34     p.cnt=0;
     35     p.time=0;
     36     q.push(p);
     37     while(!q.empty())
     38     {
     39         p=q.front();
     40         q.pop();
     41         if(p.time>=t-1)
     42             return -1;
     43         for(i=0;i<4;i++)
     44         {
     45             temp=p;
     46             temp.x+=dir[i][0];
     47             temp.y+=dir[i][1];
     48             temp.time=p.time+1;
     49             temp.cnt=p.cnt;
     50             if(!judge(temp))
     51                 continue;
     52             if(map[temp.x][temp.y]=='^')
     53             {
     54                 return temp.time;
     55             }
     56             if(map[temp.x][temp.y]=='@' || map[temp.x][temp.y]=='.')
     57             {
     58                 if(!flag[temp.cnt][temp.x][temp.y])
     59                 {
     60                     flag[temp.cnt][temp.x][temp.y]=1;
     61                     q.push(temp);
     62                 }
     63                 continue;
     64             }
     65             if(map[temp.x][temp.y]>='A' && map[temp.x][temp.y]<='J' && !flag[temp.cnt][temp.x][temp.y])
     66             {
     67                 cc=temp.cnt;
     68                 if((cc>>(map[temp.x][temp.y]-'A')) & 1)
     69                 {
     70                     flag[temp.cnt][temp.x][temp.y]=1;
     71                     q.push(temp);
     72                 }
     73                 continue;
     74             }
     75             if(map[temp.x][temp.y]>='a' && map[temp.x][temp.y]<='j')
     76             {
     77                 cc=1<<(map[temp.x][temp.y]-'a');
     78                 temp.cnt=cc | temp.cnt;
     79                 if(!flag[temp.cnt][temp.x][temp.y])
     80                 {
     81                     flag[temp.cnt][temp.x][temp.y]=1;
     82                     q.push(temp);
     83                 }
     84                 continue;
     85             }
     86         }
     87     }
     88     return -1;
     89 }
     90 
     91 int main()
     92 {
     93     while(~scanf("%d%d%d",&row,&col,&t))
     94     {
     95         int i,j;
     96         bool ff=false;
     97         for(i=0;i<row;i++)
     98         {
     99             scanf("%s",map[i]);
    100             if(!ff)
    101             {
    102                 for(j=0;j<col;j++)
    103                 {
    104                     if(map[i][j]=='@')
    105                     {
    106                         x1=i;
    107                         y1=j;
    108                         ff=true;
    109                         break;
    110                     }
    111                 }
    112             }
    113         }
    114         memset(flag,0,sizeof(flag));
    115         flag[0][x1][y1]=1;
    116         int res=bfs();
    117         printf("%d\n",res);
    118     }
    119     return 0;
    120 }

    这是一道简单的状态标记广搜题目,刚开始卡死在状态那个地方,后来想通了,题目中最多拥有10把钥匙,也就是2^10方(十位二进制中的每一位代表着不同钥匙,0代表没有拥有,1代表拥有此钥匙)作为状态标记,所以定义一个三维的flag[][][]标记函数,进行普通的广搜,注意遇到小写字母的时候记得进行左移 再与前一个状态值进行或运算,例如,假设已经用了A 门的要是,状态此时因该是0000000001,意思是拥有了a,如果下一次遇到了J门的钥匙,也就是j,那就应该是(1<<10) | (0000000001),那么此时的状态应该是1000000001,当遇到已经拥有钥匙的门的时候再进行右移运算,例如下一次遇到J门时,我们应该先将1000000001右移10位再与 1进行(&)与运算,如果拥有J门的钥匙 应该是1&1=1 ,是真值,可以通过,如果没有,则0&1=0,是假值,则无法通过。

    剩下的就是一般的左右上下的移动 判断。

    值得让我吸取教训的是,在定义了一个队列的时候,在使用前必须判断队列里面是否为空,如果不为空,则必须置空,也就是这里让我WA了两三次,就是少了

    while(!q.empty())
    q.pop();

    这一句。

    写下这篇来告诫自己下次小心。

     
  • 相关阅读:
    打印水仙花数
    打印从1到k之间的所有素数
    Fibonacci数列小程序
    Fibonacci数
    水仙花数
    猴子吃桃问题
    5个数求最值—南阳acm
    三个数从小到大排序—南阳acm
    南阳acm奇偶数分离
    find the safest road--hdu1596
  • 原文地址:https://www.cnblogs.com/ouyangduoduo/p/3026047.html
Copyright © 2020-2023  润新知