这道题提交的时候都战战兢兢,一道核心思想为BFS的题目也可以出的这么刁钻
-
这道题一个非常亮点的地方,在于求的是线段数目最短,而不是路径长度最短,最开始一直WA在这里了(一个最短路径也许会很曲折的拐很多弯,而线段数目最短也许走的很远,但实际上线段数目少)
-
这就给BFS使用出了一个大难题,因为如果还按照常规的一次走一步然后入一个点到队列的想法,就会导致bfs队列中节点一个很重要的性质不能满足,这部分可以详见算法导论(队列中节点的距离值是不减的,并且最小值和最大值差距最大是1之类的性质)
-
所以,解法是一个方向搜索,一次走到底
-
此外无脑step 4个方向走一遍固然可以解决问题,可是,仔细想来会出现同一水平(或垂直)方向回来会走的毛病,此处可以进行剪枝,在构造step数组的时候,稍微留了个心眼,使得处在水平方向或是垂直方向的两个反方向数组序列号和为3(详见代码)进行优化,效率显著...
其实这道题很久之前做过一次,但还是被卡死,还是不够熟练,好在这次更深刻体会了一把
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;
const int maxw= 80;
char bod[maxw][maxw];
int step[4][2]= {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};
int w, h;
int dis[maxw][maxw], vis[maxw][maxw], fa[maxw][maxw];
int BFS(const int &x1, const int &y1, const int &x2, const int &y2)
{
memset(vis, 0, sizeof(vis));
queue<pair<int, int> > Q;
vis[y1][x1]= 1;
dis[y1][x1]= 0;
fa[y1][x1]= -1;
Q.push(make_pair(y1, x1));
int y, x, ny, nx;
int v, flag;
while (!Q.empty()){
pair<int, int> tp= Q.front();
Q.pop();
y= tp.first;
x= tp.second;
v= dis[y][x]+1;
for (int i= 0; i< 4; ++i){
if (3== i+fa[y][x] || i== fa[y][x]){
continue;
}
flag= 1;
ny= y+step[i][0];
nx= x+step[i][1];
while (ny>= 0 && ny<= h && nx>= 0 && nx<= w && (flag= ' '== bod[ny][nx])){
if (!vis[ny][nx]){
vis[ny][nx]= 1;
dis[ny][nx]= v;
fa[ny][nx]= i;
Q.push(make_pair(ny, nx));
}
ny+= step[i][0];
nx+= step[i][1];
}
if (!flag){
if (y2== ny && x2== nx){
return v;
}
}
}
}
return -1;
}
int main()
{
int ks_bd= 0, ks_p;
int x1, y1, x2, y2;
int ans;
while (~scanf("%d %d%*c", &w, &h) && w){
ks_p= 0;
memset(bod[0], ' ', (w+2)*sizeof(char));
memset(bod[h+1], ' ', (w+2)*sizeof(char));
++w;
for (int i= 1; i<= h; ++i){
bod[i][0]= ' ';
scanf("%[^
]%*c", bod[i]+1);
bod[i][w]= ' ';
}
++h;
printf("Board #%d:
", ++ks_bd);
while (scanf("%d %d %d %d", &x1, &y1, &x2, &y2) && x1){
ans= BFS(x1, y1, x2, y2);
if (-1== ans){
printf("Pair %d: impossible.
", ++ks_p);
}
else{
printf("Pair %d: %d segments.
", ++ks_p, ans);
}
}
putchar('
');
}
return 0;
}