首页 > 代码库 > POJ 1556 The Doors

POJ 1556 The Doors

线段求交+spfa.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define maxn 1050
#define eps 1e-8
#define inf 0x3f3f3f3f
using namespace std;
struct point
{
    double x,y;
    point(double x,double y):x(x),y(y) {}
    point() {}
    friend point operator -(point x,point y)
    {
        return point(x.x-y.x,x.y-y.y);
    }
    friend bool operator ==(point x,point y)
    {
        return ((x.x==y.x) && (x.y==y.y));
    }
}p[maxn*50];
struct line
{
    point x,y,dt;
    line (point x,point y,point dt):x(x),y(y),dt(dt) {}
    line () {}
    friend double operator *(line x,line y)
    {
        return x.x.x*y.x.y-x.x.y*y.x.x;
    }
    friend bool operator ==(line x,line y)
    {
        return ((x.x==y.x) && (x.y==y.y));
    }
}l[maxn*50];
struct edge
{
    int v,nxt;
    double w;
}e[maxn*100];
int n,g[maxn*50],tot1=0,tot2=0,nume=1;
double x,a,b,c,d,dis[maxn*50];
queue <int> q;
bool vis[maxn*50];
double dist(point x,point y) {return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
void addedge(int u,int v,double w)
{
    e[++nume].v=v;e[nume].w=w;
    e[nume].nxt=g[u];g[u]=nume;
}
point ask_cross(line x,line y)
{
    double a,b,c,d,e,f;
    a=x.x.y-x.y.y;b=x.y.x-x.x.x;c=x.x.x*x.y.y-x.x.y*x.y.x;
    d=y.x.y-y.y.y;e=y.y.x-y.x.x;f=y.x.x*y.y.y-y.x.y*y.y.x;
    return point((b*f-c*e)/(a*e-b*d),(a*f-c*d)/(b*d-a*e));
}
bool isin(point x,line y)
{
    point ret=x-y.x;
    if (!y.dt.x)
    {
        double mn=min(y.x.y,y.y.y),mx=max(y.x.y,y.y.y);
        return (x.y>mn && x.y<mx);
    }
    else return (ret.x/y.dt.x>0 && ret.x/y.dt.x<1);
}
bool check(point x,point y)
{
    line now=line(x,y,y-x);
    for (int i=1;i<=tot2;i++)
    {
        if (fabs(now*l[i])<eps) continue;
        point cross=ask_cross(now,l[i]);
        if (isin(cross,l[i]) && isin(cross,now))
            return false;
    }
    return true;
}
void spfa()
{
    while (!q.empty()) q.pop();memset(vis,false,sizeof(vis));
    for (int i=2;i<=tot1;i++) dis[i]=inf;
    dis[1]=0;vis[1]=true;q.push(1);
    while (!q.empty())
    {
        int head=q.front();q.pop();
        for (int i=g[head];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (dis[v]>dis[head]+e[i].w)
            {
                dis[v]=dis[head]+e[i].w;
                if (!vis[v]) {q.push(v);vis[v]=true;}
            }
        }
        vis[head]=false;
    }
}
int main()
{
    for (;;)
    {
        memset(g,0,sizeof(g));nume=1;tot1=tot2=0;
        scanf("%d",&n);if (n==-1) break;
        p[++tot1]=point(0,5);
        for (int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf%lf",&x,&a,&b,&c,&d);
            p[++tot1]=point(x,a);p[++tot1]=point(x,b);p[++tot1]=point(x,c);p[++tot1]=point(x,d);
            l[++tot2]=line(point(x,0),point(x,a),point(x,a)-point(x,0));
            l[++tot2]=line(point(x,b),point(x,c),point(x,c)-point(x,b));
            l[++tot2]=line(point(x,d),point(x,10),point(x,10)-point(x,d));
        }
        p[++tot1]=point(10,5);
        for (int i=1;i<=tot1;i++)
            for (int j=i+1;j<=tot1;j++)
            {
                if (check(p[i],p[j]))
                {
                    addedge(i,j,dist(p[i],p[j])); 
                    addedge(j,i,dist(p[i],p[j]));
                }
            }
        spfa();
        printf("%.2f\n",dis[tot1]);
    }
    return 0;
}

 

POJ 1556 The Doors