zoukankan      html  css  js  c++  java
  • POJ 1556

    题目链接:http://poj.org/problem?id=1556

    Time Limit: 1000MS Memory Limit: 10000K

    Description

    You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x = 0, x = 10, y = 0, and y = 10. The initial and final points of the path are always (0, 5) and (10, 5). There will also be from 0 to 18 vertical walls inside the chamber, each with two doorways. The figure below illustrates such a chamber and also shows the path of minimal length. 

    Input

    The input data for the illustrated chamber would appear as follows. 


    4 2 7 8 9 
    7 3 4.5 6 7 

    The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1. 

    Output

    The output should contain one line of output for each chamber. The line should contain the minimal path length rounded to two decimal places past the decimal point, and always showing the two decimal places past the decimal point. The line should contain no blanks.

    Sample Input

    1
    5 4 6 7 8
    2
    4 2 7 8 9
    7 3 4.5 6 7
    -1

    Sample Output

    10.00
    10.06

    题意:

    给出一个(0,0)(0,10)(10,0)(10,10)的正方形房子,里面有一些墙,每堵墙上有两扇门;

    求从(0,5)到(10,5)的最短距离;

    题解:

    是一道不错的题目,一定程度上结合了计算几何和最短路;

    建一个有向图,把(0,5)作为起始点,(10,5)作为目标点,其他所有墙上的门的两个端点也加入到这个有向图中;

    尝试枚举连接任意两个点,只有当这两个点之间没有墙阻隔,这连个点才可能连接起来;

    所有能连接起来的两个点都作为一条有向边加入到有向图中,并且靠左的作为u,靠右的作为v,而两点之间的距离作为w;

    最后,我们只要求出起始点和目标点之间的最短路即可。

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #define MAXN 4*20
    #define INF 0x3f3f3f3f
    using namespace std;
    
    //--------------------------------------计算几何模板 - st--------------------------------------
    
    const double eps = 1e-6;
    
    struct Point{
        double x,y;
        Point(double tx=0,double ty=0):x(tx),y(ty){}
    };
    typedef Point Vctor;
    
    //向量的加减乘除
    Vctor operator + (Vctor A,Vctor B){return Vctor(A.x+B.x,A.y+B.y);}
    Vctor operator - (Point A,Point B){return Vctor(A.x-B.x,A.y-B.y);}
    Vctor operator * (Vctor A,double p){return Vctor(A.x*p,A.y*p);}
    Vctor operator / (Vctor A,double p){return Vctor(A.x/p,A.y/p);}
    
    int dcmp(double x)
    {
        if(fabs(x)<eps) return 0;
        else return (x<0)?(-1):(1);
    }
    bool operator == (Point A,Point B){return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;}
    
    //向量的点积,长度,夹角
    double Dot(Vctor A,Vctor B){return A.x*B.x+A.y*B.y;}
    double Length(Vctor A){return sqrt(Dot(A,A));}
    double Angle(Vctor A,Vctor B){return acos(Dot(A,B)/Length(A)/Length(B));}
    
    //叉积,三角形面积
    double Cross(Vctor A,Vctor B){return A.x*B.y-A.y*B.x;}
    double TriangleArea(Point A,Point B,Point C){return Cross(B-A,C-A);}
    
    //判断线段是否规范相交
    bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
    {
        double c1 = Cross(a2 - a1,b1 - a1), c2 = Cross(a2 - a1,b2 - a1),
               c3 = Cross(b2 - b1,a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
        return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
    }
    
    //--------------------------------------计算几何模板 - ed--------------------------------------
    
    //--------------------------------------spfa算法 - st--------------------------------------
    double d[MAXN];
    double mp[MAXN][MAXN];
    bool vis[MAXN];
    void init(int n){for(int i=0;i<n;i++) for(int j=0;j<n;j++) mp[i][j]=0;}
    void addedge(int u,int v,double w){mp[u][v]=w;}
    void spfa(int st,int n)
    {
        for(int i=0;i<n;i++)
        {
            i==st ? d[i]=0 : d[i]=INF;
            vis[i]=0;
        }
        queue<int> q;
        q.push(st);
        vis[st]=1;
        while(!q.empty())
        {
            int u=q.front();q.pop();vis[u]=0;
            for(int v=0;v<n;v++)
            {
                if(u==v || mp[u][v]==0) continue;
                double tmp=d[v];
                if(d[v]>d[u]+mp[u][v]) d[v]=d[u]+mp[u][v];
                if(d[v]<tmp && !vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    //--------------------------------------spfa算法 - ed--------------------------------------
    
    int n;
    vector<Point> p;
    int main()
    {
        while(scanf("%d",&n) && n!=-1)
        {
            p.clear();
            p.push_back(Point(0,5));
            for(int i=1;i<=n;i++)
            {
                double x,y1,y2,y3,y4;
                scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
                p.push_back(Point(x,y1));
                p.push_back(Point(x,y2));
                p.push_back(Point(x,y3));
                p.push_back(Point(x,y4));
            }
            p.push_back(Point(10,5));
    
            int _size=p.size();
            init(_size);
            for(int i=0;i<_size;i++)
            {
                for(int j=i+1;j<_size;j++)
                {
                    if(p[i].x==p[j].x) continue;
    
                    bool ok=1;
                    for(int k=i+1;k<j;k++)
                    {
                        if(k%4==1)
                        {
                            if(SegmentProperIntersection(p[i],p[j],p[k],Point(p[k].x,0)))
                            {
                                ok=0;
                                break;
                            }
                        }
                        else if(k%4==2)
                        {
                            if(SegmentProperIntersection(p[i],p[j],p[k],p[k+1]))
                            {
                                ok=0;
                                break;
                            }
                        }
                        else if(k%4==3)
                        {
                            if(SegmentProperIntersection(p[i],p[j],p[k],p[k-1]))
                            {
                                ok=0;
                                break;
                            }
                        }
                        else if(k%4==0)
                        {
                            if(SegmentProperIntersection(p[i],p[j],p[k],Point(p[k].x,10)))
                            {
                                ok=0;
                                break;
                            }
                        }
                    }
                    if(ok) addedge(i,j,Length(p[i]-p[j]));
                }
            }
    
            spfa(0,_size);
            printf("%.2f
    ",d[_size-1]);
        }
    }
  • 相关阅读:
    二分优化lis和STL函数
    D8 双连通分量
    Apicloud 之按两次后退键退出应用
    Js 之正则验证手机号、QQ、身份证等
    PHP 之循环创建文件夹
    招聘系统
    Mysql 之根据经纬度按距离排序
    PHP 之根据两个经纬度计算距离
    PHP 之Mysql优化
    Tkinter 之使用PAGE工具开发GUI界面
  • 原文地址:https://www.cnblogs.com/dilthey/p/7801317.html
Copyright © 2011-2022 走看看