搜索进阶-状压搜索

故名思义,就是在搜索过程中应用了状态压缩思想

常为BFS与状态压缩结合(因为用DFS不好保存状态,写起来麻烦些)

直接啃代码理解就行。

Description

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;
int n,m,t;
char mp[25][25];
int vis[25][25][1300];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int sx,sy,ex,ey;
int cnt=-1;
struct node
{
    int x,y;
    int key;
    int step;
};
bool judge(node p)
{
    if(p.x<0||p.x>=n||p.y<0||p.y>=m) return false;
    if(mp[p.x][p.y]=='*'||vis[p.x][p.y][p.key]) return false;
    return true;
}
void bfs()
{
    node n,p;
    n.x=sx;
    n.y=sy;
    n.key=0;
    n.step=0;
    vis[n.x][n.y][n.key]=1;
    queue<node> q;
    q.push(n);
    while(!q.empty())
    {
        n=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            p=n;
            p.x+=dx[i];
            p.y+=dy[i];
            p.step=n.step+1;
            if(judge(p))
            {
              if(p.step>=t) return;
              if(p.x==ex&&p.y==ey)
              {
                  cnt=p.step;
                  return;
              }
              else if(mp[p.x][p.y]=='.'||mp[p.x][p.y]=='@')
              {
                  if(!vis[p.x][p.y][p.key])
                  {
                    vis[p.x][p.y][p.key]=1;
                    q.push(p);
                  }
                  else
                    continue;
              }
              else if(mp[p.x][p.y]>='A'&&mp[p.x][p.y]<='J')
              {
                  int flag=(p.key>>(mp[p.x][p.y]-'A'))&1;
                  if(flag)
                  {
                      vis[p.x][p.y][p.key]=1;
                      q.push(p);
                  }
              }
              else
              {
                  p.key=p.key|(1<<(mp[p.x][p.y]-'a'));
                  if(!vis[p.x][p.y][p.key])
                  {
                      vis[p.x][p.y][p.key]=1;
                      q.push(p);
                  }
              }
            }
        }
    }
    return;
}

int main()
{
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        getchar();
        cnt=-1;
        int flag=1;
        for(int i=0;i<n;i++)
        {
          for(int j=0;j<m;j++)
          {
            scanf("%c",&mp[i][j]);
            if(mp[i][j]=='@')
            {
                sx=i;
                sy=j;
            }
            if(mp[i][j]=='^')
            {
                ex=i;
                ey=j;
            }
          }
          getchar();
        }
          memset(vis,0,sizeof vis);
          bfs();
          printf("%d\n",cnt);
    }
    return 0;
}

 这里钥匙的状态应用了状态压缩的思想。

这里的vis[  ] 要用三维,因为对于相同的点钥匙的状态不同也算作不同的状态。

猜你喜欢

转载自blog.csdn.net/hzaukotete/article/details/81225965
今日推荐