POJ - 1556 【計算幾何 + 最短路】

Tryna1發表於2020-10-14

The Doors

題意 : 給出一個房間,大小為10×10,起點在(0,5),終點在(10,5),房間中有若干堵牆,問從起點到終點的最短路徑。

題解 : 列舉每兩點,如果這兩個點構成的線段沒有與房間中的任何一線段相交,那麼就建一條邊,所有邊建完之後跑一邊迪傑斯特拉就好了。

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;    
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){
    if(fabs(x) < eps) return 0;
    else return x < 0?-1:1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator + (Point B){return Point(x + B.x,y + B.y);}
    Point operator - (Point B){return Point(x - B.x,y - B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;
struct Line{
    Point p1,p2;
    Line(){}
    Line(Point p1,Point p2):p1(p1),p2(p2){}
    Line(Point p,double angle){    //y = kx + b
        p1 = p;
        if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
        else {p2 = (p1 + Point(1,tan(angle)));}
    }
    Line(double a,double b,double c){    //ax + by + c = 0
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a,0);
            p2 = Point(-c/a,1);
        }
        else{
            p1 = Point(0,-c/b);
            p2 = Point(1,(-c - a)/b);
        }
    }
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
    return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}
bool Cross_segment(Point a, Point b, Point c, Point d){         
    double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
    double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
    return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;           
}
int n;
double x, y;
bool judge(Line v){
    for(int k = 1; k <= 6 * n; k+=2){
        if(Cross_segment(L[1].p1, L[1].p2, P[k], P[k + 1]) == 1) return false;
    }
    return true;
}
double d[maxn];
int vis[maxn];
struct node{
	int to;
    double w;
    node(int to_,double w_){
		to = to_,w = w_;
	}
};
vector<node>v[maxn];
void Dij(){
	 d[0] = 0;
	 while(1){
	 	double min1=999999.0 ;
        int z = -1;
	 	for(int i = 0;i < 6 * n + 1; i++){
	 		if(d[i] < min1 && !vis[i]){
	 			min1 = d[i];
	 			z = i;
			 }
		 }
		 if(z == -1)  break;
		 vis[z] = 1;
		 for(int i = 0;i < v[z].size(); i++){
		 	int vv = v[z][i].to;
            double dis = v[z][i].w;
            if(d[vv] > dis + d[z]) d[vv] = dis + d[z];
		 }
	 }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    while(cin>>n){
        if(n == -1) break;
        for(int i = 0;i <= 6 * n + 1;i++){
		    v[i].clear();
		    vis[i]=0;
		    d[i]=99999.0;
	    }
        P[0].x = 0;
        P[0].y = 5;
        for(int i = 1; i <= n; i++){
            cin>>x;
            P[(i - 1) * 6 + 1].x = x;
            P[(i - 1) * 6 + 1].y = 0;
            for(int j = 2; j <= 5; j++){
                cin>>y;
                P[(i - 1) * 6 + j].x = x;
                P[(i - 1) * 6 + j].y = y;
            }
            P[(i - 1) * 6 + 6].x = x;
            P[(i - 1) * 6 + 6].y = 10;
        }
        P[6 * n + 1].x = 10;
        P[6 * n + 1].y = 5;   //true
        for(int i = 0; i < 6 * n + 1; i++){
            if((i % 6 == 1 || i % 6 == 0) && i != 0) continue;
            for(int j = i + 1; j <= 6 * n + 1; j++){
                if((j % 6 == 1 || j % 6 == 0) && j != 6 * n + 1) continue;
                L[1].p1.x = P[i].x;
                L[1].p1.y = P[i].y;
                L[1].p2.x = P[j].x;
                L[1].p2.y = P[j].y;
                if(judge(L[1])){
                    double dist = Dist(P[i] ,P[j]);
                    v[i].push_back(node(j, dist));
                }
            }
        }
        Dij();
        cout<<fixed<<setprecision(2)<<d[6 * n + 1]<<endl;
    }
    return 0;
}

相關文章