A 迷宫(maze2.pas/c/cpp)
TL:1S ML:128MB
【Description】
你所在的迷宫可以用 N 行 M 列的矩阵来描述:
图标 含义
‘# ’ 墙,无法通过
. 地面,可以通过
小写字母(a、b、c、…、z) 钥匙,可以打开标有对应大写字母的门
大写字母(A、B、C、…、Z) 门,可以被标有对应小写字母的钥匙打开
shift+4 你的初始位置
& 迷宫的出口位置
迷宫的四周都有墙,所以你无法走出这片 N*M 的区域,只能从”&”处离开迷宫,你只能
向东西南北四个方向走。
你的任务是,计算出走出迷宫需要的最少步数是多少?
【Input】
第 1 行两个正整数 N 和 M,表示迷宫的长和宽;
第 2 行一个正整数 P,表示门和钥匙的数量;
第 3 行至第 N+2 行,描述整个迷宫。
【Output】
一个整数,为走出迷宫需要的最少步数或-1(如果不可能走出迷宫)。
【Sample Input】
5 5
1
&A..shift+4
####.
…#.
.#.#.
a#…
【Sample Output】
28
【Sample Input】
1 4
1
&aAshift+4
【Sample Output】
-1
【Hint】
对于 30%:1 <= N, M <= 15
另外存在 10%:P=0
另外存在 10%:P=1
另外存在 20%:P=2
对于 100%:1<=N,M<=50,0<=P<=10,保证迷宫中”$”、”&”和所有大小写字
母只出现一次,钥匙和门的标号只会出现字母表中的前 P 个字母。
mdzz…..昨天刚做了毒药解药,这个题没看出来是二进制状压。
这个地图上有钥匙和门,所以可能出现的情况是:有些门把终点挡住了。所以用普通迷宫的判重方法是不行的,我们需要这样:bool vis[maxn][maxn][1<<11];
第一二维表示横纵坐标,第三维表示是个二进制数,如01010011之类的,0代表当前没有拿到某个门的钥匙,1代表拿到。
这样的话,搜到钥匙就可以往回走了…
#include<cstdio>
#include<queue>
using namespace std;
int n,m,p;
const int maxn=60;
int sx,sy;
int ex,ey;
struct meico
{
int x;
int y;
int key;
int d;
};
queue<meico>q;
int x1[]={0,1,0,-1,0};
int y1[]={0,0,1,0,-1};
int map[maxn][maxn];
bool vis[maxn][maxn][1<<11];
char hah[maxn];
int key[maxn][maxn];
int door[maxn][maxn];
bool flag;
bool pd(int x,int y,int k)
{
if(x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y][k])
return true;
return false;
}
void bfs()
{
while(!q.empty())
{
for(int i=1;i<=4;i++)
{
int x=q.front().x;
int y=q.front().y;
int k=q.front().key;
int d=q.front().d;
x+=x1[i];
y+=y1[i];
if(map[x][y])
{
if(x==ex&&y==ey)
{
printf("%d",d+1);
flag=1;
return;
}
if(key[x][y])
{
k|=(1<<key[x][y]);
if(!vis[x][y][k])
{
vis[x][y][k]=1;
q.push((meico){x,y,k,d+1});
}
continue;
}
else if(door[x][y])
{
if((k>>door[x][y]&1))
{
if(!vis[x][y][k])
{
vis[x][y][k]=1;
q.push((meico){x,y,k,d+1});
}
}
continue;
}
else
{
if(pd(x,y,k))
{
vis[x][y][k]=1;
q.push((meico){x,y,k,d+1});
}
}
}
}
q.pop();
}
}
int main()
{
freopen("maze2.in","r",stdin);
freopen("maze2.out","w",stdout);
scanf("%d%d%d\n",&n,&m,&p);
for(int i=1;i<=n;i++)
{
scanf("%s",hah);
for(int j=0;j<=m;j++)
{
map[i][j+1]=1;
if(hah[j]=='#')
map[i][j+1]=0;
else if(hah[j]>='a'&&hah[j]<='z')
key[i][j+1]=hah[j]-'a'+1;
else if(hah[j]>='A'&&hah[j]<='Z')
door[i][j+1]=hah[j]-'A'+1;
else if(hah[j]=='$')
sx=i,sy=j+1;
else if(hah[j]=='&')
ex=i,ey=j+1;
}
}
q.push((meico){sx,sy,0,0});
bfs();
if(!flag)
puts("-1");
return 0;
}