题目链接

最短路+几何

把端点当作节点,两点之间如果没有墙阻拦就连一条双向边,权值为两点之间的距离,最后求最短路。

两点之间是否被阻拦,可以用叉积来判断两线段是否相交。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <queue>

using namespace std;

const int INF = 0x3f3f3f3f;
const double eps = 1e-4;

struct P {
	double x, y[6];
} p[100];

pair<double, double> node[100];

double G[100][100], d[100];
bool vis[100];

bool check(P sag_1[], P sag_2[]) {
	double x1, y1, x2, y2, x3, y3;
	x1 = sag_1[1].x-sag_1[0].x;
	y1 = sag_1[1].y[0]-sag_1[0].y[0];
	x2 = sag_2[0].x-sag_1[0].x;
	y2 = sag_2[0].y[0]-sag_1[0].y[0];
	x3 = sag_2[1].x-sag_1[0].x;
	y3 = sag_2[1].y[0]-sag_1[0].y[0];
	if((x1*y2-y1*x2)*(x1*y3-y1*x3) < 0) return false;
	else return true;
}

double dis(pair<double, double> a, pair<double, double> b) {
	return sqrt((a.first-b.first)*(a.first-b.first)+(a.second-b.second)*(a.second-b.second));
}

void spfa(int s, int t) {
	for(int i = 0; i <= t; ++i) {
		vis[i] = false; d[i] = INF;
	}
	d[s] = 0;
	queue <int> qu;
	qu.push(s); vis[s] = true;
	
	while(!qu.empty()) {
		int u = qu.front(); qu.pop();
		vis[u] = false;
		
		for(int v = 0; v <= t; ++v) {
			if(d[v] > d[u]+G[u][v]) {
				d[v] = d[u]+G[u][v];
				if(!vis[v]) {
					vis[v] = true;
					qu.push(v);
				}
			}
		}
	}
	printf("%.2f\n", d[t]);
}

int main(void)
{
	int n;
	while(scanf("%d", &n) != EOF) {
		if(n == -1) break;
		int index = 0;
		node[index].first = 0;
		node[index++].second = 5;
		for(int i = 0; i < n; ++i) {
			scanf("%lf", &p[i].x);
			for(int j = 0; j < 4; ++j) {
				scanf("%lf", &p[i].y[j]);
				node[index].first = p[i].x;
				node[index++].second = p[i].y[j];
			}
		}
		node[index].first = 10;
		node[index++].second = 5;
		
		for(int i = 0; i < index; ++i) {
			for(int j = 0; j < index; ++j) G[i][j] = INF;
		}
		for(int i = 0; i < index; ++i) {
			for(int j = i+1; j < index; ++j) {
				if(node[i].first == node[j].first) continue;
				bool ok = true;
				for(int k = 0; k < n; ++k) {
					if(p[k].x <= node[i].first) continue;
					if(node[j].first <= p[k].x) continue;
					for(int l = 0; l < 3; ++l) {
						P sag_1[5], sag_2[5];
						sag_1[0].x = node[i].first; sag_1[0].y[0] = node[i].second;
						sag_1[1].x = node[j].first; sag_1[1].y[0] = node[j].second;
						
						sag_2[0].x = sag_2[1].x = p[k].x;
						if(l == 0) sag_2[0].y[0] = 0, sag_2[1].y[0] = p[k].y[0];
						else if(l == 2) sag_2[0].y[0] = p[k].y[3], sag_2[1].y[0] = 10;
						else sag_2[0].y[0] = p[k].y[1], sag_2[1].y[0] = p[k].y[2];
						
						if(!check(sag_1, sag_2)) {
							ok = false; break;
						}
					}
					if(!ok) break;
				}
				if(ok) {
					G[i][j] = G[j][i] = dis(node[i], node[j]);	
				}
			}
		}
		spfa(0, index-1);
	}
	return 0;
}