[poj1556]:The Doors

来源:互联网 发布:中国股市周期 知乎 编辑:程序博客网 时间:2024/05/16 10:58

传送门
计算几何基础题——第四题
就是暴力连边最短路,判是否可以连边的时候用叉积判一下就好了。
具体可以看我的代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<cstdlib>#define ll long longusing namespace std;inline int read(){    int x=0;char ch=' ';int f=1;    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();    if(ch=='-')f=-1,ch=getchar();    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();    return x*f;}const int N=300;const double eps=1e-12;struct Point{    double x,y;    Point(){}    Point(double _x,double _y):x(_x),y(_y){}    inline Point operator - (const Point& b) const {return Point(x-b.x,y-b.y);}    inline double operator * (const Point& b) const {return x*b.y-y*b.x;}}P[N];inline double dis(const Point& a,const Point& b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}inline int dcmp(double x){    if(fabs(x)<eps)return 0;    return x>eps?1:-1;}struct Line{    Point s,t;    Line(){}    Line(Point _s,Point _t):s(_s),t(_t){}}L[N];inline bool check(const Line& a,const Line& b){    bool flag1=dcmp(((b.s-a.s)*(b.t-a.s))*((b.s-a.t)*(b.t-a.t)))<0;    bool flag2=dcmp(((a.s-b.s)*(a.t-b.s))*((a.s-b.t)*(a.t-b.t)))<0;    return flag1&&flag2;}int n,cnt,cnt2;int tot,head[N],Next[N*N],to[N*N],q[N],inq[N];double val[N*N],d[N];inline void add(int x,int y,double l){to[++tot]=y;Next[tot]=head[x];val[tot]=l;head[x]=tot;}inline void addedge(int x,int y){    Line Ask=Line(P[x],P[y]);    for(int i=1;i<=cnt2;i++)if(check(Ask,L[i]))return;    add(x,y,dis(P[x],P[y]));add(y,x,dis(P[x],P[y]));}inline void spfa(){    for(int i=1;i<=cnt;i++)d[i]=1e9,inq[i]=0;    int l=1,r=1;d[1]=0;q[1]=1;inq[1]=1;    while(l<=r){        int x=q[l++];        for(int i=head[x];i;i=Next[i]){            int u=to[i];            if(d[x]+val[i]<d[u]){                d[u]=d[x]+val[i];                if(!inq[u]){                    inq[u]=1;                    q[++r]=u;                }            }        }        inq[x]=0;    }}int main(){    while(1){        memset(head,0,sizeof(head));        cnt=0;cnt2=0;tot=0;        n=read();if(n==-1)break;        cnt=1;P[1].x=0;P[1].y=5;        for(int i=1;i<=n;i++){            double x;scanf("%lf",&x);            int lim=cnt;            for(int j=1;j<=4;j++){                double y;scanf("%lf",&y);                P[++cnt]=Point(x,y);                for(int k=1;k<=lim;k++)addedge(k,cnt);            }            L[++cnt2]=Line(P[cnt],Point(x,10));            L[++cnt2]=Line(P[cnt-2],P[cnt-1]);            L[++cnt2]=Line(Point(x,0),P[cnt-3]);        }        P[++cnt].x=10;P[cnt].y=5;        for(int i=1;i<cnt;i++)addedge(i,cnt);        spfa();        printf("%.2lf\n",d[cnt]);    }    return 0;}