POJ 1556 The Doors(线段交+最短路)

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>

using namespace std;

const double eps = 1e-8;
int sgn(double x)
{
    if(fabs(x) < eps)return 0;
    if(x < 0) return -1;
    else return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y)
    {
        x = _x;y = _y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    double operator ^(const Point &b)const
    {
        return x*b.y - y*b.x;
    }
    double operator *(const Point &b)const
    {
        return x*b.x + y*b.y;
    }
};
struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;e = _e;
    }
};
//判断线段相交
bool inter(Line l1,Line l2)
{
    return
        max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
        sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) <= 0 &&
        sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) <= 0;
}
double dist(Point a,Point b)
{
    return sqrt((b-a)*(b-a));
}
const int MAXN = 100;
Line line[MAXN];
double dis[MAXN][MAXN];
const double INF = 1e20;
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    double x,y1,y2,y3,y4;
    while(scanf("%d",&n) == 1)
    {
        if(n == -1) break;
        for(int i = 1;i <= n;i++)
        {
            scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
            line[2*i-1] = Line(Point(x,y1),Point(x,y2));
            line[2*i] = Line(Point(x,y3),Point(x,y4));
        }
        for(int i = 0;i <= 4*n+1;i++)
            for(int j = 0;j <= 4*n+1;j++)
            {
                if(i == j)dis[i][j] = 0;
                else dis[i][j] = INF;
            }
        for(int i = 1;i <= 4*n;i++)
        {
            int lid = (i+3)/4;
            bool flag = true;
            Point tmp;
            if(i&1)tmp = line[(i+1)/2].s;
            else tmp = line[(i+1)/2].e;
            for(int j = 1;j < lid;j++)
                if(inter(line[2*j-1],Line(Point(0,5),tmp)) == false
                        && inter(line[2*j],Line(Point(0,5),tmp)) == false)
                    flag = false;
            if(flag)dis[0][i] =dis[i][0] = dist(Point(0,5),tmp);
            flag = true;
            for(int j = lid+1;j <= n;j++)
                if(inter(line[2*j-1],Line(Point(10,5),tmp)) == false
                        && inter(line[2*j],Line(Point(10,5),tmp)) == false)
                    flag = false;
            if(flag)dis[i][4*n+1] =dis[4*n+1][i] = dist(Point(10,5),tmp);
        }
        for(int i = 1;i <= 4*n;i++)
            for(int j = i+1;j <=4*n;j++)
            {
                int lid1 = (i+3)/4;
                int lid2 = (j+3)/4;
                bool flag = true;
                Point p1,p2;
                if(i&1)p1 = line[(i+1)/2].s;
                else p1 = line[(i+1)/2].e;
                if(j&1)p2 = line[(j+1)/2].s;
                else p2 = line[(j+1)/2].e;
                for(int k = lid1+1;k < lid2;k++)
                    if(inter(line[2*k-1],Line(p1,p2)) == false
                            && inter(line[2*k],Line(p1,p2)) == false)
                        flag = false;
                if(flag) dis[i][j] = dis[j][i] = dist(p1,p2);
            }
        bool flag = true;
        for(int i = 1;i <= n;i++)
            if(inter(line[2*i-1],Line(Point(0,5),Point(10,5))) == false
                    && inter(line[2*i],Line(Point(0,5),Point(10,5))) == false)
                flag = false;
        if(flag)dis[0][4*n+1] = dis[4*n+1][0] = 10;
        for(int k = 0;k <= 4*n+1;k++)
            for(int i = 0;i <= 4*n+1;i++)
                for(int j = 0;j <= 4*n+1;j++)
                    if(dis[i][k] + dis[k][j] < dis[i][j])
                        dis[i][j] = dis[i][k] + dis[k][j];
        printf("%.2lf\n",dis[0][4*n+1]);
    }

    return 0;
}

  

时间: 2024-10-15 13:16:30

POJ 1556 The Doors(线段交+最短路)的相关文章

POJ 1556 The Doors 线段交 dijkstra

LINK 题意:在$10*10$的几何平面内,给出n条垂直x轴的线,且在线上开了两个口,起点为$(0, 5)$,终点为$(10, 5)$,问起点到终点不与其他线段相交的情况下的最小距离. 思路:将每个开口的两端点作为一个节点,再枚举点与点间能否直接到达(判相交),以此建图求最短路. /** @Date : 2017-07-11 16:17:31 * @FileName: POJ 1556 线段交+dijkstra 计算几何.cpp * @Platform: Windows * @Author :

POJ 1556 - The Doors 线段相交不含端点

POJ 1556 - The Doors题意:    在 10x10 的空间里有很多垂直的墙,不能穿墙,问你从(0,5) 到 (10,5)的最短距离是多少.    分析:        要么直达,要么一定是墙的边缘点之间以及起始点.终点的连线.        所以先枚举墙上每一点到其他点的直线可达距离,就是要判定该线段是否与墙相交(不含端点).        然后最短路. 1 #include <iostream> 2 #include <cstdio> 3 #include &l

POJ 1556 The Doors --几何,最短路

题意: 给一个正方形,从左边界的中点走到右边界的中点,中间有一些墙,问最短的距离是多少. 解法: 将起点,终点和所有墙的接触到空地的点存下来,然后两两之间如果没有线段(墙)阻隔,就建边,最后跑一个最短路SPFA,即可得出答案. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <a

Poj 1556 The Doors 计算几何+最短路

其实本题非常的无脑,无脑拍完1A,写到blog里只因为TM无脑拍也拍了很久啊= = #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdl

POJ 3304 Segments 基础线段交判断

LINK 题意:询问是否存在直线,使得所有线段在其上的投影拥有公共点 思路:如果投影拥有公共区域,那么从投影的公共区域作垂线,显然能够与所有线段相交,那么题目转换为询问是否存在直线与所有线段相交.判断相交先求叉积再用跨立定理.枚举每个线段的起始结束点作为直线起点终点遍历即可. /** @Date : 2017-07-12 14:35:44 * @FileName: POJ 3304 基础线段交判断.cpp * @Platform: Windows * @Author : Lweleth ([em

简单几何(线段相交+最短路) POJ 1556 The Doors

题目传送门 题意:从(0, 5)走到(10, 5),中间有一些门,走的路是直线,问最短的距离 分析:关键是建图,可以保存所有的点,两点连通的条件是线段和中间的线段都不相交,建立有向图,然后用Dijkstra跑最短路.好题! /************************************************ * Author :Running_Time * Created Time :2015/10/24 星期六 09:48:49 * File Name :POJ_1556.cpp

POJ 1556 The Doors(简单计算几何+最短路)

●赘述题目 10*10的房间内,有竖着的一些墙(不超过18个).问从点(0,5)到(10,5)的最短路. 按照输入样例,输入的连续5个数,x,y1,y2,y3,y4,表示(x,0--y1),(x,y2--y3),(x,y4--10)是墙壁. ●题解 方法:建图(用到简单计算几何)+最短路 ○记录下每个端点. ○包含起点,终点,以及每个墙的可以走的端点,如下图: ○然后枚举点,尝试两两组合连(线段)边,若该线不会撞在墙上,即不会与墙壁线段相交,就add_adge(). 效果图如下: 如何判断呢?

POJ 1556 The Doors

计算几何+最短路 枚举线段是否相交建图,然后跑最短路 #include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int maxn=1000+10; const double eps=1e-8; int n; int totP,totL

最短路+线段交 POJ 1556 好题

1 // 最短路+线段交 POJ 1556 好题 2 // 题意:从(0,5)到(10,5)的最短距离,中间有n堵墙,每堵上有两扇门可以通过 3 // 思路:先存图.直接n^2来暴力,不好写.分成三部分,起点 终点和之间的点:中间点之间:起点和终点的距离 4 // n最大为18所以直接n^3最短路 5 6 7 #include <cstdio> 8 #include <cstring> 9 #include <iostream> 10 #include <algo