路徑只包含水平或者豎直的直線段。路徑不能穿過別的遊戲卡片。但是允許路徑臨時離開矩形板。
下面是一個例子:
你現在要在小遊戲裏面判斷是否存在一條滿足題意的路徑能連接給定的兩個遊戲卡片。
這道題最早遇見是在高二的縣裏的模擬賽的時候,感覺是一個經典的問題。
分析,首先因爲要求是最少的線段,實際就是用最少的轉彎,那就每個方向光搜出去應該是能到的最遠處內的所有點都是應該在該層中被加入隊列的。
於是按照線段的轉折次數爲層數進行光搜即可。其中要注意一些細節。
該題出現在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;
}