游戏在一个分割成w * h个长方格子的矩形板上进行。如图所示,每个长方格子上可以有一张游戏卡片,也可以没有。当下面的情况满足时,我们认为两个游戏卡片之间有一条路径相连:
路径只包含水平或者竖直的直线段。路径不能穿过别的游戏卡片。但是允许路径临时离开矩形板。
下面是一个例子:
这里在(1, 3)和(4, 4)处的游戏卡片是可以相连的。而在 (2, 3) 和 (3, 4) 处的游戏卡是不相连的,因为连接他们的每条路径都必须要穿过别的游戏卡片。
路径只包含水平或者竖直的直线段。路径不能穿过别的游戏卡片。但是允许路径临时离开矩形板。
下面是一个例子:

你现在要在小游戏里面判断是否存在一条满足题意的路径能连接给定的两个游戏卡片。
这道题最早遇见是在高二的县里的模拟赛的时候,感觉是一个经典的问题。
分析,首先因为要求是最少的线段,实际就是用最少的转弯,那就每个方向光搜出去应该是能到的最远处内的所有点都是应该在该层中被加入队列的。
于是按照线段的转折次数为层数进行光搜即可。其中要注意一些细节。
该题出现在P大的编程网格上,岁月匆匆感慨万千,因为细节没有处理好,导致大数据上WA了若干次。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstring>
#include <queue>
using namespace std;
const int maxN = 100+10;
const int dir[4][2]= {0,1,0,-1,-1,0,1,0};
char s[maxN], map[maxN][maxN];
int sx,sy,tx,ty,n,m,ans;
int f[maxN][maxN][4],arrive[maxN][maxN][4];
struct Node{
int x,y,Dir;
}node,newNode;
queue<Node> q;
bool inside(int x,int y)
{
return (x>=0 && x<=n+1 && y>=0 && y<=m+1);
}
bool ok()
{
memset(arrive,0,sizeof(arrive));
memset(f,127,sizeof(f));
bool canArrive = false;
while (!q.empty()) q.pop();
for (int k = 0; k < 4;++k)
{
node.x = sx; node.y = sy; node.Dir = k;
q.push(node);
f[sx][sy][k]=1;
arrive[sx][sy][k]=true;
}
while (!q.empty())
{
Node now = q.front();
q.pop();
arrive[now.x][now.y][now.Dir] == false;
for (int k = 0; k < 4; ++k)
for (int step = 1; step <= maxN ; ++step)
{
int x=now.x+dir[k][0]*step;
int y=now.y+dir[k][1]*step;
if ( !inside(x,y)) break;
if (tx == x && ty == y)
{
f[x][y][k]=min(f[x][y][k],
f[now.x][now.y][now.Dir]+(now.Dir != k));
canArrive = true;
}
if (map[x][y] == 'X' ) break;
if (f[now.x][now.y][now.Dir]+(now.Dir != k)< f[x][y][k])
{
f[x][y][k]=f[now.x][now.y][now.Dir]+(now.Dir != k);
if (!arrive[x][y][k])
{
arrive[x][y][k]=true;
newNode.x = x; newNode.y = y; newNode.Dir = k;
q.push(newNode);
}
}
}
}
return canArrive;
}
int main()
{
int Test = 0;
while (scanf("%d%d",&m,&n)==2)
{
if (m==0 && n==0) break;
getchar();
printf("Board #%d:\n",++Test);
for (int i = 0; i <= n+1; ++i)
for (int j = 0; j <= m+1; ++j) map[i][j]='S';
for (int i = 1;i <= n; ++i)
{
gets(s);
for (int j = 1; j <= m ;++j)
map[i][j] = s[j-1];
}
int Pair = 0;
while(scanf("%d%d%d%d",&sy,&sx,&ty,&tx))
{
if (sx+sy+tx+ty == 0) break;
if (!ok()) printf("Pair %d: impossible.\n",++Pair);
else
{
int ans = maxN * maxN;
for (int k = 0 ; k < 4; ++k)
ans=min(ans,f[tx][ty][k]);
printf("Pair %d: %d segments.\n",++Pair,ans);
}
}
}
return 0;
}