一个不算太难的Dfs问题,可以理解为找到一条到终点的最短路径同时记下变了几次方向。
题解都写在注释里了。
//小游戏
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxw = 80;
char board[maxw][maxw];
bool mark[maxw][maxw]; //标记数组
int minStep, w, h, to[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};
//定义的深搜状态为从x1,y1到x2,y2,当前分为step个线段,当前方向是f
void Dfs(int x1, int y1, int x2, int y2, int step, int f)
{
if(step > minStep) return; //最优化剪枝
if(x1==x2 && y1==y2){ //终点
if(minStep > step) minStep = step;
return;
}
for(int i = 0; i < 4; i++){ //对每个可以走的位置
int x = x1+to[i][0], y = y1+to[i][1];
//越界最多一格且是没有走过的空格或终点
if((x>=0) && (x<=w+1) && (y>=0) && (y<=h+1) && (((board[y][x])==' ' && (mark[y][x]==false))
|| ((x==x2) && (y==y2) && (board[y][x]=='X')))){
mark[y][x] = true; //标记为走过
//上一步搜索方向和当前方向相同step不变,否则step+1
if(f==i) Dfs(x, y, x2, y2, step, i);
else Dfs(x, y, x2, y2, step+1, i);
mark[y][x] = false; //回溯
}
}
}
int main()
{
int index1 = 0;
while(scanf("%d%d",&w,&h) != EOF){
if(w==0 && h==0) break;
index1++;
printf("Board #%d:\n",index1);
for(int i = 0; i < 75+2; i++)
board[0][i] = board[i][0] = ' ';
for(int i = 1; i <= h; i++){
getchar();
for(int j = 1; j <= w; j++)
board[i][j] = getchar();
}
//在矩形最外层加一圈空格
for(int i = 0; i <= w; i++)
board[h+1][i+1] = ' ';
for(int i = 0; i <= h; i++)
board[i+1][w+1] = ' ';
int x1, y1, x2, y2, index2 = 0;
while(scanf("%d%d%d%d",&x1, &y1, &x2, &y2)!=EOF && x1>0){
index2++;
minStep = 100000;
memset(mark, false, sizeof(mark));
Dfs(x1, y1, x2, y2, 0, -1);
if(minStep < 100000) printf("Pair %d: %d segments.\n",index2,minStep);
else printf("Pair %d: impossible.\n",index2);
}
printf("\n");
}
return 0;
}