POJ 1556 The Doors(线段与线段是否相交,建图最短路,包含模板)
思路:这道题要想到,走端点一定是最短的。所以我们可以将这道题看成一个图,看看端点与端点之间是否能够构称边。这时候我们就要穷举任意两点,如果两点之间没有线段隔着,说明可以联通,这时候添加一条边。添加完之后跑一遍dijkstra算法,就跑出来了。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include <cstdio>
using namespace std;
#define ll long long
struct Point
{
double x,y;
Point(double x= 0, double y = 0):x(x),y(y){}
};
typedef Point Vector;
const int INF = 0x3f3f;
Vector operator-(Point A,Point B)
{
return Vector(A.x-B.x,A.y-B.y);
}
Vector operator *(Vector A, double p)
{
return Vector(A.x*p, A.y*p);
}
Vector operator +(Vector A, Vector B){
return Vector(A.x+B.x, A.y+B.y);
}
Vector operator /(Vector A, double p){return Vector(A.x/p, A.y/p);}
double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y;}
double Length(Vector A){ return sqrt(Dot(A, A));}
double Cross(Vector A, Vector B){return A.x*B.y-A.y*B.x;}
double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
const double eps = 1e-6;
int sgn(double x){
if(fabs(x) < eps)
return 0;
if(x < 0)
return -1;
return 1;
}
struct Line{
Point v, p;
Line(){}
Line(Point v, Point p):v(v), p(p){}
Point point(double t){
return v+(p-v)*t;//·µ»ØµãP = v + (p - v)*t
}
}line[1050];
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);
double c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
return (sgn(c1)*sgn(c2) < 0 && sgn(c3)*sgn(c4) < 0);
}
const int M = 200;
struct Edge
{
int from, to;
double dist;
Edge(int u, int v, double d):from(u),to(v),dist(d) {}
};
struct HeapNode
{
double d;
int u;
HeapNode(double d, int u):d(d),u(u){}
bool operator< (const HeapNode & rhs) const{
return d >rhs.d;
}
};
struct Dijkstra
{
int n, m;
vector<Edge>edges;
vector<int>G[M];
bool done[M];
double dis[M]; //距离
int p[M]; //最短路中的上一条弧
void init(int n)
{
this ->n = n;
for(int i = 0; i<n;i++)
G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, double dist)
{
edges.push_back(Edge(from, to, dist));
m = edges.size();
G[from].push_back(m-1);
}
void dijkstra(int s)
{
priority_queue<HeapNode>Q;
for(int i = 0; i<n; i++) dis[i] = INF;
dis[s] = 0;
memset(done, 0, sizeof(done));
Q.push(HeapNode(0,s));
while(!Q.empty())
{
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for(int i = 0; i<G[u].size(); i++)
{
Edge &e = edges[G[u][i]];
if(dis[e.to] > dis[u] + e.dist)
{
dis[e.to] = dis[u] + e.dist;
p[e.to] =edges[ G[u][i]].from;
Q.push(HeapNode(dis[e.to], e.to));
}
}
}
}
};
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
if(n == -1)
return 0;
Dijkstra dj;
dj.init(199);
int cnt = 0;
int ct = -1;
Point p[10000];
p[++ct] = Point(0,5);
for(int i = 1;i<=n;i++)
{
double a,b,c,d,e;
scanf("%lf%lf%lf%lf%lf", &a, &b, &c, &d, &e);
line[++cnt] = Line(Point(a,0), Point(a,b));
line[++cnt] = Line(Point(a,c), Point(a,d));
line[++cnt] = Line(Point(a,e), Point(a,10));
p[++ct] = Point(a,b);
p[++ct] = Point(a,c);
p[++ct] = Point(a,d);
p[++ct] = Point(a,e);
}
p[++ct]=Point(10, 5);
bool flag = true;
double mat[M][M];
for(int i = 0;i<=ct;i++)
{
for(int j = i+1;j<=ct;j++)
{
flag = true;
for(int k = 1;k<=cnt;k++)
{
if(SegmentProperIntersection(p[i],p[j],line[k].v,line[k].p))
{
flag = false;
break;
}
}
if(flag)
{
//cout<<i<<j<<dis(p[i],p[j])<<endl;
dj.AddEdge(i, j, dis(p[i],p[j]));
dj.AddEdge(j, i, dis(p[i],p[j]));
}
}
}
dj.dijkstra(0);
printf("%.2lf\n",dj.dis[ct]);
}
return 0;
}