题目描述
要求你写一个程序,在一个地图中,找到最小步数将每个鬼移动到他们指定的位置。
地图包含一些小方格。每格要么是墙(鬼不能进入)要么是走廊(鬼能进入)。每一步里,你可以同时移动任意数量的鬼。每个鬼要么待在原地不动,要么移动到相邻的格子里(相邻的格子有公共边),如果移动满足下列条件,则移动是可行的。
1. 没有一个以上的鬼在同一个格子里。
2. 没有一对鬼在一步里交换了位置。
例如,假设鬼的位置是如下图所示的,其中sharp(#)表示墙,空格表示走廊,a,b,c表示鬼:
经过一步移动后,地图可以变成如下的样子:
Input
输入包括最多10组数据,每组数据包含一幅地图。输入格式如下:
第一行的w,h和n表示地图的宽度和高度,n表示鬼的数目,他们满足:
4<=w<=16, 4<=h<=16, 1<=n<=3
接下来h行,每行w个字符:
一个#表示墙
一个小写字母表示鬼的初始位置(该位置也是走廊)
一个大写字母表示鬼的目标位置(该位置也是走廊)
一个空格表示空的走廊。
在每幅地图里,前n个小写字母和前n个大写字母表示鬼的初始位置及鬼的目标位置。我们需要将小写字母表示的鬼移动到对应的大写字母的位置里。
最后一组数据后一行有三个0
Output
对每组数据输出一行一个整数,表示最小的移动步数。
Sample Input
Sample Output
分析
这什么鬼题
好像还真是鬼题
我们想到用编号法将两维的空间变为图论的一维,连边,用fa,b,c表示a鬼所在的位置,b鬼所在的位置,c鬼所在的位置,压进队列里用位运算来做,然后显然BFS先BFS到的最优,退出
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#define rep(i,a,b) for (i=a;i<=b;i++)
using namespace std;
int w,h,n;
int f[200][200][200];
int list[200];
int g[200][6];
int s[4],e[4];
int wyx(int x,int y,int z)
{
return (x<<16)|(y<<8)|z;
}
bool judge(int x,int y,int vx,int vy)
{
return x==vy&&y==vx||vx==vy;
}
void init()
{
int i,j,number=0;
int num[17][17];
int x[200],y[200];
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};
char c;
memset(num,0,sizeof(num));
rep(i,1,h)
rep(j,1,w)
{
do
{
scanf("%c",&c);
}
while (c=='\n');
if (c!='#')
{
num[i][j]=++number;
x[number]=i;
y[number]=j;
if (97<=c&&c<=99)
s[c-96]=number;
if (65<=c&&c<=67)
e[c-64]=number;
}
}
rep(i,1,number)
{
rep(j,0,4)
{
int x1=x[i]+dx[j],y1=y[i]+dy[j];
if (x1>h||y1>w||x1<1||y1<1||num[x1][y1]==0) continue;
list[i]++;
g[i][list[i]]=num[x1][y1];
}
}
if (n<=2)
{
list[++number]=1;
g[number][1]=number;
s[3]=number;
e[3]=number;
}
if (n==1)
{
list[++number]=1;
g[number][1]=number;
s[2]=number;
e[2]=number;
}
}
void bfs()
{
int a,b,c;
int va,vb,vc;
int i,j,k;
queue<int> q;
q.push(wyx(s[1],s[2],s[3]));
f[s[1]][s[2]][s[3]]=0;
while (!q.empty())
{
int o=q.front();
q.pop();
a=(o>>16)&255;b=(o>>8)&255;c=o&255;
if (a==e[1]&&b==e[2]&&c==e[3]) break;
rep(i,1,list[a])
{
va=g[a][i];
rep(j,1,list[b])
{
vb=g[b][j];
if (judge(a,b,va,vb)) continue;
rep(k,1,list[c])
{
vc=g[c][k];
if (judge(a,c,va,vc)) continue;
if (judge(b,c,vb,vc)) continue;
if (f[va][vb][vc]<0)
{
f[va][vb][vc]=f[a][b][c]+1;
q.push(wyx(va,vb,vc));
}
}
}
}
}
}
int main()
{
while (1)
{
scanf("%d%d%d",&w,&h,&n);
if (w==h&&h==n&&n==0) break;
memset(f,-1,sizeof(f));
memset(g,0,sizeof(g));
memset(list,0,sizeof(list));
memset(s,0,sizeof(s));
memset(e,0,sizeof(e));
init();
bfs();
printf("%d\n",f[e[1]][e[2]][e[3]]);
}
}