题意:1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但是幸好麦克得到了迷宫的地形图。
迷宫的外形是一个长方形,其在南北方向被划分为N行,在东西方向被划分为M列,于是整个迷宫被划分为N*M个单元。我们用一个有序数对(单元的行号,单元的列号)来表示单元位置。南北或东西方向相邻的两个单元之间可以互通,或者存在一扇锁着的门,又或者存在一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分为P类,打开同一类的门的钥匙相同,打开不同类的门的钥匙不同。
大兵瑞恩被关押在迷宫的东南角,即(N,M)单元里,并已经昏迷。迷宫只有一个入口,在西北角,也就是说,麦克可以直接进入(1,1)单元。另外,麦克从一个单元移动到另一个相邻单元的时间为1,拿取所在单元的钥匙的时间以及用钥匙开门的时间忽略不计。
你的任务是帮助麦克以最快的方式抵达瑞恩所在单元,营救大兵瑞恩。
想法:典型的状态压缩,把麦克的位置和身上钥匙可以开的门记录下来,然后有一个地方就是,一个地点可能会有多把钥匙,这个要想到。然后把可以开那些门用二进制的1表示就好了,应为最多也就10个门。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int nodes=15;
int n,m,p;
bool wall[nodes][nodes][nodes][nodes];
int door[nodes][nodes][nodes][nodes];
int key[nodes][nodes];
bool vis[1<<12][nodes][nodes];
int dir[4][2]={1,0,0,1,0,-1,-1,0};
struct node
{
int x,y;
int sta;
int tim;
};
void init()
{
memset(wall,false,sizeof(wall));
memset(door,0,sizeof(door));
memset(key,0,sizeof(key));
}
void bfs()
{
memset(vis,false,sizeof(vis));
node head,nxt;
queue<node>q;
while(!q.empty()) q.pop();
head.x=1;head.y=1;head.sta=0;head.tim=0;
if(key[1][1])
{
head.sta|=key[1][1];
}
q.push(head);
vis[head.sta][1][1]=true;
while(!q.empty())
{
head=q.front();
q.pop();
if(head.x==n&&head.y==m)
{
printf("%d\n",head.tim);
return;
}
for(int i=0;i<4;i++)
{
nxt.x=head.x+dir[i][0];
nxt.y=head.y+dir[i][1];
nxt.tim=head.tim+1;
nxt.sta=head.sta;
if(wall[head.x][head.y][nxt.x][nxt.y]) continue;
if(nxt.x<1||nxt.x>n||nxt.y<1||nxt.y>m) continue;
int dn=door[head.x][head.y][nxt.x][nxt.y];
if(dn)
{
if(!(1<<(dn-1)&nxt.sta)) continue;
}
if(key[nxt.x][nxt.y])
{
nxt.sta|=key[nxt.x][nxt.y];
}
if(!vis[nxt.sta][nxt.x][nxt.y])
{
vis[nxt.sta][nxt.x][nxt.y]=true;
q.push(nxt);
}
}
}
printf("-1\n");
return;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&p))
{
init();
int K;
scanf("%d",&K);
for(int i=1;i<=K;i++)
{
int x1,y1,x2,y2,g;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
if(!g) wall[x1][y1][x2][y2]=wall[x2][y2][x1][y1]=true;
else door[x1][y1][x2][y2]=door[x2][y2][x1][y1]=g;
}
int S;
scanf("%d",&S);
for(int i=1;i<=S;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
key[x][y]|=1<<(z-1);
}
bfs();
}
return 0;
}