poj 1556 The Doors

计算几何+最短路

通过线段是否完全相交判断两点的连通性。

 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

const double inf=1e10;
const double EP=1e-8;
struct Point{
    double x, y;
}p[105];            //4*n+2
struct Segline{
    Point s, e;
}seg[65];           //3*n
int n, vis[105];
double a[105][105], d[105];
double dist(Point p1, Point p2){
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double x_mult(Point sp, Point ep, Point op){
    return (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);
}
bool intersect(Segline l1, Segline l2){
    if((x_mult(l1.s,l2.e,l2.s)*x_mult(l1.e,l2.e,l2.s)<-EP)&&
    (x_mult(l2.s,l1.e,l1.s)*x_mult(l2.e,l1.e,l1.s)<-EP))
    return true;
    return false;
}

void init(){
    p[0].x=0;p[0].y=5;
    p[4*n+1].x=10;p[4*n+1].y=5;
    Point p1, p2;
    int i, j, k;
    for(i=0; i<n; i++){
        scanf("%lf%lf%lf%lf%lf", &p[i*4+1].x, &p[i*4+1].y, &p[i*4+2].y, &p[i*4+3].y, &p[i*4+4].y);
        p1.x=p2.x=p[i*4+2].x=p[i*4+3].x=p[i*4+4].x=p[i*4+1].x;
        p1.y=0;p2.y=10;
        seg[i*3].s=p1;seg[i*3].e=p[i*4+1];
        seg[i*3+1].s=p[i*4+2];seg[i*3+1].e=p[i*4+3];
        seg[i*3+2].s=p[i*4+4];seg[i*3+2].e=p2;
    }
    Segline st;
    for(i=0; i<4*n+2; i++)
    for(j=i+1; j<4*n+2; j++){
        a[i][j]=a[j][i]=dist(p[i], p[j]);
        for(k=(i+3)/4*3; k<(j-1)/4*3; k++){
            st.s=p[i];st.e=p[j];
            if(intersect(st, seg[k])){
                a[i][j]=a[j][i]=inf;
                break;
            }
        }
    }
}

void dijkstra(int st){
    int i, j, flag;
    double tmp;
    for(i=0; i<4*n+2; i++){
        d[i]=a[st][i];
    }
    memset(vis, 0, sizeof(vis));
    vis[st]=1;
    for(i=0; i<4*n+1; i++){
        tmp=inf;
        for(j=0; j<4*n+2; j++){
            if(!vis[j]&&d[j]<tmp){
                tmp=d[j];
                flag=j;
            }
        }
        vis[flag]=1;
        for(j=0; j<4*n+2; j++){
            if(!vis[j]&&d[j]>d[flag]+a[flag][j])
                d[j]=d[flag]+a[flag][j];
        }

    }
}

void solve(){
    dijkstra(0);
    printf("%.2f\n", d[4*n+1]);
}

int main(){
    //freopen("1.txt", "r", stdin);
    int T;
    while(scanf("%d", &n)&&n!=-1){
        init();
        solve();
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值