POJ 1556 The Doors(计算几何+最短路)

POJ 1556 The Doors

题意:在一个矩形里,从 ( 0 , 5 ) ( 10 , 5 ) (0,5)\rightarrow(10,5) 的最路径,中间会有 n n 座墙,每个墙有两个门。
题解:把所有的门的点坐标预处理出来,把墙看成线段,从起点开始往后连边建图,对于没有被墙阻隔的连边,然后跑个最短路即可。

代码

/*************************************************************************
    > File Name: poj1556.cc
    > Author: sqwlly
    > Mail: [email protected] 
    > Created Time: 2019年11月01日 星期五 16时05分51秒
 ************************************************************************/
#include<iostream>
#include<cmath>
#include<vector>
#include<iomanip>
#include<queue>
using namespace std;
const double eps = 1e-8;
#define zero(x) ((fabs(x) < eps ? 1 : 0))
#define sgn(x) (fabs(x) < eps ? 0 : ((x) < 0 ? -1 : 1))

struct point
{
    double x,y;
    point(double a = 0, double b = 0) { x = a, y = b; }
    point operator - (const point& b) const { return point(x - b.x, y - b.y); }
    point operator + (const point& b) const { return point(x + b.x, y + b.y); }
    // 两点是否重合
    bool operator == (const point& b) { return zero(x - b.x) && zero(y - b.y); }
    // 点积(以原点为基准)
    double operator * (const point& b) { return x * b.x + y * b.y; }
    // 叉积(以原点为基准)
    double operator ^ (const point& b) { return x * b.y - y * b.x; }
    // 绕P点逆时针旋转a弧度后的点
    point rotate(point b, double a)
    {
        double dx, dy;
        (*this - b).split(dx, dy);
        double tx = dx * cos(a) - dy * sin(a);
        double ty = dx * sin(a) - dy * cos(a);
        return point(tx, ty) + b;
    }
    // 点坐标分别赋值到a和b
    void split(double& a, double& b) {a = x, b = y; }
};

struct line
{
    point s, e;
    line() {}
    line(point _s, point _e) { s = _s, e = _e; }
};
double dist(point a, point b) { return sqrt((a - b) * (a - b)); }

bool segxseg(line l1,line l2)
{
	return
		max(l1.s.x, l1.e.x) >= min(l2.s.x, l2.e.x) &&
		max(l2.s.x, l2.e.x) >= min(l1.s.x, l1.e.x) &&
		max(l1.s.y, l1.e.y) >= min(l2.s.y, l2.e.y) &&
		max(l2.s.y, l2.e.y) >= min(l1.s.y, l1.e.y) &&
		sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= 0 &&
		sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= 0;
}

struct door{
	double y1, y2;
};
const int N = 200, INF = 1E9;
#define P pair<double,int>

struct wall{
	double x;
	door d[2];
	line l[3];
}w[N];

vector<pair<int,double> > E[N];
vector<point> p[N];

void construct(vector<point> v, vector<line> block, int n)
{
	for(int i = 0; i < v.size(); ++i) {
		for(int j = i + 1; j < v.size(); ++j) {
			bool ok = 1;
			for(int k = 0; k < block.size(); ++k) {
				if(segxseg({v[i],v[j]}, block[k]) && (!(v[i] == block[k].s)) && (!(v[i] == block[k].e))
						&& (!(v[j] == block[k].s)) && (!(v[j] == block[k].e))) {
					ok = 0;
					break;
				}
			}
			if(ok)
			E[i].push_back(make_pair(j, dist(v[i],v[j])));
		}
	}
}

struct Dijkstra{
	priority_queue<P, vector<P>, greater<P> > pq;
	double dis[N];
	int n;

	void dijkstra(int s)
	{
		for(int i = 0; i <= n; ++i) {
			dis[i] = INF;
		}
		pq.push(P(dis[s] = 0, s));
		while(!pq.empty()) {
			P cur = pq.top(); pq.pop();
			int u = cur.second;
			if(dis[u] < cur.first) continue;
			for(int i = 0; i < E[u].size(); ++i) {
				int v = E[u][i].first;
				double w = E[u][i].second;
				if(dis[v] > dis[u] + w) {
					dis[v] = dis[u] + w;
					pq.push(P(dis[v], v));
				}
			}
		}
		//for(int i = 0; i <= n; ++i) {
		//	cout << i << ' ' << dis[i] << "\n";
		//}
	}
};

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
    ios::sync_with_stdio(false); cin.tie(0);
	int n;

	while(cin >> n && (~n)) {
		for(int i = 0; i < N; ++i) {
			E[i].clear();
		}
		vector<point> v;;
		vector<line> block;
		v.push_back(point(0,5));
		for(int i = 0; i < n; ++i) {
			cin >> w[i].x;
			for(int j = 0; j < 2; ++j) {
				cin >> w[i].d[j].y1 >> w[i].d[j].y2;
				v.push_back({w[i].x, w[i].d[j].y1});
				v.push_back({w[i].x, w[i].d[j].y2});
			}
			line a,b,c;
			a = {{w[i].x,0},{w[i].x,w[i].d[0].y1}};
			b = {{w[i].x,w[i].d[0].y2},{w[i].x,w[i].d[1].y1}};
			c = {{w[i].x,w[i].d[1].y2},{w[i].x,10}};
			block.push_back(a);
			block.push_back(b);
			block.push_back(c);
		}
		v.push_back({10,5});
		construct(v, block, n);
/*		for(int i = 0; i < E->size(); ++i) {
			cout << E[i].size() << '\n';
			for(int j = 0; j < E[i].size(); ++j) {
				cout << i << "->" << E[i][j].first << ' ' << E[i][j].second <<  endl;
			}
		}
		cout << "end\n";*/
		Dijkstra solve;
		solve.n = v.size();
		solve.dijkstra(0);
		cout << fixed << setprecision(2) << solve.dis[solve.n - 1] << '\n';
	}
    return 0;
}

发布了219 篇原创文章 · 获赞 23 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Eternally831143/article/details/102870953