http://acm.hdu.edu.cn/showproblem.php?pid=2531
Problem Description
在美式足球中,四分卫负责指挥整只球队的进攻战术和跑位,以及给接球员传球的任务。四分卫是一只球队进攻组最重要的球员,而且一般身体都相对比较弱小,所以通常球队会安排5-7名大汉来保护他,其中站在四分卫前方、排成一线的5名球员称为进攻锋线,他们通常都是135公斤左右的壮汉。 对防守方来说,攻击对手的四分卫当然是最直接的限制对手进攻的方法。如果效果好,就可以在对方四分卫传球之前将其按翻在地,称之为擒杀。擒杀是最好的鼓舞防守队士气的方法,因为对方连传球的机会都没有,进攻就结束了,还必须倒退一些距离开球。凶狠的擒杀甚至能够将对方的四分卫弄伤,从而迫使对方更换这个进攻核心。 在本题中,输入给出准备擒杀四分卫的防守球员的位置、对方每个进攻锋线球员的位置以及对方四分卫的位置,你的任务是求出这名准备擒杀的防守球员至少要移动多少步,才能够擒杀对方四分卫。 假设对方进攻锋线和四分卫在这个过程中都不会移动。只有1名防守球员,防守球员只要碰到对方四分卫就算擒杀。 所有的球员都是一块连续的、不中空的2维区域。防守球员不可以从进攻锋线的身体上穿过,也不可以从界外穿过(只能走空地)。 防守队员不可以转动身体,只能平移。防守队员的身体所有部分向同一个方向(上、下、左、右)移动1格的过程叫做1步。
Input
输入包含多组数据。每组数据第一行都是两个整数H,W(0<H,W<=100),表示整个区域的高度和宽度,H=W=0表示输入结束。接下来有H行,每行W个字符。每个字符如果是’.’,表示这里是空地,如果是’O’,表示是进攻锋线队员的身体,如果是’D’,表示是准备擒杀的防守球员的身体,如果是’Q’,表示是四分卫的身体。 输入保证符合上面的条件。防守球员的身体总共不超过20格。
Output
对每组数据,输出包含擒杀所需最少步数的一行。如果不能擒杀,输出带’Impossible’的一行。
Sample Input
6 6 .Q.... QQ..OO .OO..O ...O.O OO.O.. ....DD 7 7 .Q..... QQ.OOO. ...O... O...... OO..OO. .O..... .....DD 0 0
Sample Output
Impossible 9
思路:
将整体用 一个点x,y加上其他点的相对位移来表示,身体的每一个部分用一个数字来标记依次标为:1,2,3,4,5... 移动过程中,相同的标记点不能重复走过,也就是说,身体的某个部分走过的点,不能再走第二遍,而其他点可以,例如,第一个节点标记为1,它不能再走标记为1的点。
具体算法C++代码如下:
1 #include<iostream> 2 #include<queue> 3 using namespace std; 4 char cmap[110][110]; //定义map 5 int mark[110][110]; //定义标记 6 struct Node 7 { 8 int x,y,step; 9 }d,p; //节点,注意节点只 存其中一个点即可 10 int bx[30],by[30]; //存有相对位置的数组 11 int cx[]={1,-1,0,0}; 12 int cy[]={0,0,-1,1}; 13 int bfs(int len,int m,int n,int x,int y) 14 { 15 int i,j; 16 queue<Node> q; 17 memset(mark,0,sizeof(mark)); 18 d.x=x; 19 d.y=y; 20 d.step=0; 21 q.push(d); 22 for(i=0;i<len;i++) 23 mark[bx[i]][by[i]]=i+1; //用位置标记 24 while(!q.empty()) 25 { 26 d=q.front(); 27 q.pop(); 28 for(i=0;i<len;i++) 29 if(cmap[d.x+bx[i]][d.y+by[i]]=='Q') 30 return d.step; 31 for(i=0;i<4;i++) 32 { 33 p.x=d.x+cx[i]; 34 p.y=d.y+cy[i]; 35 p.step=d.step+1; 36 37 //进行条件判断 38 for(j=0;j<len;j++) 39 { 40 int tx,ty; 41 tx=p.x+bx[j]; 42 ty=p.y+by[j]; 43 if(cmap[tx][ty]=='O'||tx<0||tx>=m||ty<0||ty>=n||mark[tx][ty]==j+1) 44 break; 45 } 46 if(j<len) 47 continue; //若是break出来的就不进入push和标记 48 q.push(p); 49 50 //标记 51 for(j=0;j<len;j++) 52 { 53 int tx,ty; 54 tx=p.x+bx[j]; 55 ty=p.y+by[j]; 56 mark[tx][ty]=j+1; 57 } 58 } 59 } 60 return 0; 61 } 62 int main() 63 { 64 int m,n; 65 while(~scanf("%d%d",&m,&n)) 66 { 67 if(!m&&!n) 68 break; 69 int i,j,k; 70 for(i=0;i<m;i++) 71 scanf("%s",cmap[i]); 72 for(k=i=0;i<m;i++) 73 for(j=0;j<n;j++) 74 { 75 if(cmap[i][j]=='D') 76 { 77 bx[k]=i; 78 by[k]=j; 79 k++; 80 } 81 } 82 int sx=bx[0],sy=by[0]; 83 for(i=0;i<k;i++) //生成相对位置数组 84 { 85 bx[i]-=sx; 86 by[i]-=sy; 87 } 88 int ans=bfs(k,m,n,sx,sy); 89 if(ans) 90 printf("%d\n",ans); 91 else 92 puts("Impossible"); 93 } 94 return 0; 95 }