Description
众所周知(怎么又是众所周知),仙剑的迷宫是难走的要命,某人就在仙四的女罗岩困了很长时间。
我们可以把女罗岩的地图抽象成n*n的地图,我们现在在(1,1)处,而出口在(n,n)。每次行动只能向上下左右移动一格。图中有M个机关,只有打开某个机关之后,与该机关相对应的地方才可以行走。当然,地图中还会有小怪兽,他们能够监视着他所在地区以及上下左右共五个方格,我们不愿意与他们战斗(为了节省时间),所以他们能监视到的地方不可以行走。同样的,地图上的障碍物处也不能经过。
我们需要求出从起点到终点的最少步数。
Input
第1行,两个整数N, M。表示地图大小为N*N,机关的数量为M。
第2-N+1行,每行N个整数,每个整数i可能是0,-1,-2或者一个正整数。i=0表示该位置为一块空地,i=-1表示该位置为一个障碍物,i=-2表示该位置为一个小怪兽。如果i是一个属于[1,M]的正整数,则表示该位置为一个机关,其编号为i。如果i是一个大于M的正整数,则表示该位置为一个机关控制区域,它由编号为i-M的机关控制。
Output
一个整数,为走出迷宫所需的最少的步数。
Sample Input
6 2
0 0 0 -2 -1 2
-1 0 0 0 -1 0
-2 0 0 0 3 3
-2 0 0 -1 -1 4
0 -1 0 0 -1 0
1 0 0 0 -1 0
Sample Output
24
Hint
【样例说明】
地图如下图,S为入口,T为目标,黑色的单元格为障碍物。每个E表示一个小怪兽,(E)为小怪兽的监视范围。K1表示机关1,K2表示机关2。D1表示机关为1的控制区域,D2表示机关为2的控制区域。
最优的路线为(1,1) →(1,2) →(2,2) →(2,3) →(3,3) →(4,3) →(5,3) →(6,3) →(6,2) →(6,1)(破坏供电1) →(6,2) →(6,3) →(5,3) →(4,3) →(3,3) →(3,4) →(3,5) →(3,6) →(2,6) →(1,6)(破坏供电2) →(2,6) →(3,6) →(4.6) →(5,6) →(6,6)
n<=50 m<=16
【分析】
明显是状态压缩BFS。由于M<=16,完全可以用一个二进制数表示是否获得钥匙。
【代码】
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
queue<int>Qx;
queue<int>Qy;
queue<int>Qw;
int N,M,f[51][51][(1<<17)+5];
int dx[4]={-1,0,0,1},dy[4]={0,1,-1,0};
int Map[51][51];
bool vis[51][51][(1<<17)+5];
void _init()
{
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
scanf("%d",&Map[i][j]);
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(Map[i][j]==-2)
{
Map[i][j]=-1;
for(int k=0;k<=3;k++)
if(1<=i+dx[k]&&i+dx[k]<=N)
if(1<=j+dy[k]&&j+dy[k]<=N)
if(Map[i+dx[k]][j+dy[k]]!=-2)
Map[i+dx[k]][j+dy[k]]=-1;
}
}
void _solve()
{
int tx,ty,tw;
Qx.push(1);Qy.push(1);
if(1<=Map[1][1]&&Map[1][1]<=M)
{
Qw.push((1<<(Map[1][1]-1)));
vis[1][1][(1<<(Map[1][1]-1))]=true;
}
else
{
Qw.push(0);
vis[1][1][0]=true;
}
while(!Qx.empty())
{
tx=Qx.front();ty=Qy.front();tw=Qw.front();
Qx.pop();Qy.pop();Qw.pop();
for(int k=0;k<=3;k++)
if(1<=tx+dx[k]&&tx+dx[k]<=N)
if(1<=ty+dy[k]&&ty+dy[k]<=N)
{
int temp=Map[tx+dx[k]][ty+dy[k]];
if(tx+dx[k]==N&&ty+dy[k]==N)
{
printf("%d\n",f[tx][ty][tw]+1);
return;
}
if(temp==0)
{
if(vis[tx+dx[k]][ty+dy[k]][tw]==false)
{
f[tx+dx[k]][ty+dy[k]][tw]=f[tx][ty][tw]+1;
vis[tx+dx[k]][ty+dy[k]][tw]=true;
Qx.push(tx+dx[k]);
Qy.push(ty+dy[k]);
Qw.push(tw);
}
}
else if(1<=temp&&temp<=M)
{
if(vis[tx+dx[k]][ty+dy[k]][tw|(1<<(temp-1))]==false)
{
f[tx+dx[k]][ty+dy[k]][tw|(1<<(temp-1))]=f[tx][ty][tw]+1;
vis[tx+dx[k]][ty+dy[k]][tw|(1<<(temp-1))]=true;
Qx.push(tx+dx[k]);
Qy.push(ty+dy[k]);
Qw.push(tw|(1<<(temp-1)));
}
}
else if(M<temp)
{
int p=temp-M;
if((tw>>(p-1))&1)
{
if(vis[tx+dx[k]][ty+dy[k]][tw]==false)
{
f[tx+dx[k]][ty+dy[k]][tw]=f[tx][ty][tw]+1;
vis[tx+dx[k]][ty+dy[k]][tw]=true;
Qx.push(tx+dx[k]);
Qy.push(ty+dy[k]);
Qw.push(tw);
}
}
}
}
}
}
int main()
{
_init();
_solve();
return 0;
}