题目大意:就是矩阵中找出进攻锋线队员“O”到四分卫“Q”之间的最短距离。
做题方法:其实就是普通的迷宫问题的变形,只不过它要求的是一堆点到另一堆点的距离。方法其实很简单,把所有的O看成一个整体,然后每次判断的时候必须要所有的“O”点都满足要求。这里有个小技巧,就是每次记录该点已经访问过的时候,只要标记其中一个点就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAX=150;
char ch[MAX][MAX];
bool vis[MAX][MAX];
int d[4][2]= {{-1,0},{0,1},{0,-1},{1,0}};
struct Pt
{
int r,c;
};
struct node
{
Pt pt[22];
int step;
};
node nowp;
int num;
int bfs(int h,int w)
{
queue<node> que;
node tmp;
que.push(nowp);
vis[nowp.pt[0].r][nowp.pt[0].c]=true;
while(!que.empty())
{
nowp=que.front();
que.pop();
for(int i=0; i<4; i++)
{
int j,res=-1;
tmp.step=nowp.step+1;
for(int k=0;k<num;k++)
{
tmp.pt[k].r=nowp.pt[k].r+d[i][0];
tmp.pt[k].c=nowp.pt[k].c+d[i][1];
}
for(j=0;j<num; j++)
{
if(tmp.pt[j].r>0 && tmp.pt[j].r<=h && tmp.pt[j].c>0 && tmp.pt[j].c<=w)
{
if(vis[tmp.pt[0].r][tmp.pt[0].c] || ch[tmp.pt[j].r][tmp.pt[j].c]=='O')break;
if(ch[tmp.pt[j].r][tmp.pt[j].c]=='Q')res=tmp.step;
}
else break;
}
if(j==num)
{
if(res!=-1)return res;
else
{
que.push(tmp);
vis[tmp.pt[0].r][tmp.pt[0].c]=true;
}
}
}
}
return -1;
}
int main()
{
int ans;
int h,w;
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&h,&w)&& (h+w))
{
for(int i=1; i<=h; i++)
scanf("%s",ch[i]+1);
num=0;
memset(vis,0,sizeof(vis));
for(int i=1; i<=h; i++)
for(int j=1; j<=w; j++)
if(ch[i][j]=='D')
{
nowp.pt[num].r=i;
nowp.pt[num++].c=j;
}
nowp.step=0;
ans=bfs(h,w);
if(ans!=-1)printf("%d\n",ans);
else printf("Impossible\n");
}
return 0;
}