POJ 1101

这道题提交的时候都战战兢兢,一道核心思想为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;
}
原文地址:https://www.cnblogs.com/Idi0t-N3/p/14664834.html