状压搜索   广搜

用广搜好保存状态(钥匙)对钥匙的状态进行状态压缩,每一个位置上1或0对应有没有这种钥匙

C题:

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

Input

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

. 代表路
* 代表墙
@ 代表AveryBoy的起始位置
^ 代表地牢的出口
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

 

#include<bits/stdc++.h>
using namespace std;
char maze[25][25];
bool vis[25][25][1200];
int sx,sy,ex,ey,t,n,m;
int cnt;
int nx[4]={1,0,0,-1};
int ny[4]={0,1,-1,0};
struct node
{
    int x,y,key,step;
}st;
bool check(node temp)
{
    if(temp.x<0||temp.x>=n||temp.y<0||temp.y>=m)return false;
    else if(maze[temp.x][temp.y]=='*'||vis[temp.x][temp.y][temp.key])return false;
    else return true;
}
void bfs()
{
    node tmp,next;
    queue<node>que;
    que.push(st);
    vis[sx][sy][0]=true;
    while(!que.empty())
    {
        tmp=que.front();
        que.pop();
        for(int i=0;i<4;i++)
        {
            next=tmp;
            next.x+=nx[i];
            next.y+=ny[i];
            next.step++;
            if(next.step>=t)return;    //剪枝,若消耗时间已经>=t但还没有走到终点,则不可能逃离迷宫;
            if(check(next))
            {
                if(next.x==ex&&next.y==ey)
                {
                   if(next.step<t)cnt=next.step; //最先找到的一定最优,满足条件才给cnt赋值
                   return;
                }
                else if(maze[next.x][next.y]=='.')
                {
                    vis[next.x][next.y][next.key]=true;
                    que.push(next);
                }
                /*else if(next.x==sx&&next.y==sy)
                {
                    if(!vis[next.x][next.y][next.key])
                    {
                        vis[next.x][next.y][next.key]=true;
                        que.push(next);
                    }
                }*/
                else if(maze[next.x][next.y]>='A'&&maze[next.x][next.y]<='J') //碰到了门
                {
                    int flag=(next.key>>(maze[next.x][next.y]-'A'))&1;  //对钥匙状态压缩,看每个位置有没有门对应编号的钥匙
                    if(flag)
                    {
                        vis[next.x][next.y][next.key]=true;
                        que.push(next);
                    }
                }
                else //碰到了钥匙
                {
                    next.key=next.key|(1<<(maze[next.x][next.y]-'a'));//对手里钥匙的状态进行更新
                    if(!vis[next.x][next.y][next.key])   //看更新钥匙之后的这个位置有没有出现过;
                    {
                        vis[next.x][next.y][next.key]=true;
                        que.push(next);
                    }
                }
            }
        }
    }
    return;
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&t))
    {
      int i,j;
      cnt=-1;
      for(i=0;i<n;i++)scanf("%s",maze[i]);
      for(i=0;i<n;i++)
      {
          for(j=0;j<m;j++)
          {
               if(maze[i][j]=='@')
            {
                sx=i;
                sy=j;
                st.x=sx;
                st.y=sy;
                st.key=0;
                st.step=0;
                maze[i][j]='.';//将起点置为“可走”,接下来就不用特判
            }
            if(maze[i][j]=='^')
            {
                ex=i;
                ey=j;
            }
          }
      }
       memset(vis,false,sizeof vis);
       bfs();
       printf("%d\n",cnt);
    }
    return 0;
}
View Code

相关文章:

  • 2021-11-05
  • 2021-03-31
  • 2019-12-17
  • 2021-12-27
  • 2021-06-29
  • 2020-11-09
猜你喜欢
  • 2021-08-31
  • 2022-01-01
  • 2021-02-04
  • 2022-01-05
  • 2021-09-14
  • 2021-08-22
  • 2021-11-03
  • 2021-09-13
相关资源
相似解决方案