poj 1556 题解

题意:如图,大概猜的到了?最多18面墙,每面墙上两个门,从(0,5)走到(10,5)的最短距离,保留两位小数

题解:这道题非常贴心地按序给出墙的坐标,把每个端点当做图里面的一个节点,用O(n3)时间判断每两点之间是否能连边,判断方法为判断直线与线段是否相交(事实上是两个线段,但在这道题里面用直线交线段即可),跑一个最短路即可(既然已经到了三次方级别,干脆写了最短的Floyd)

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

#define rep(i,a,b) for (int i=a;i<=b;++i)

const double eps=1e-7;

struct point{
    double x,y;
    point(){}
    point (double a,double b): x(a),y(b) {}

    friend point operator + (const point &a,const point &b){
        return point(a.x+b.x,a.y+b.y);
    }

    friend point operator - (const point &a,const point &b){
        return point(a.x-b.x,a.y-b.y);
    }

    friend point operator * (const double &r,const point &a){
        return point(r*a.x,r*a.y);
    }

    friend bool operator == (const point &a,const point &b){
        return (abs(a.x-b.x)<eps && abs(a.y-b.y)<eps);
    }

    double norm(){
        return sqrt(x*x+y*y);
    }
};

inline double det(point a,point b) {return a.x*b.y-a.y*b.x;}
inline double dot(point a,point b) {return a.x*b.x+a.y*b.y;}
inline double dist(point a,point b) {return (a-b).norm();}

inline bool line_cross_segment(point s,point t,point a,point b)
{
    return !(det(s-a,t-a)*det(s-b,t-b)>eps);
}

int n,m;
point s[1000];
double dis[1000][1000],x,y;

bool ok(int a,int b)
{
    point ts=s[a],tt=s[b];
    if (a/4+(a%4!=0)==b/4+(b%4!=0)) return false;
    rep(i,a/4+(a%4!=0)+1,b/4+(b%4!=0)-1)
    {
        if (!line_cross_segment(ts,tt,s[(i-1)*4+1],s[(i-1)*4+2]) && !(line_cross_segment(ts,tt,s[(i-1)*4+3],s[(i-1)*4+4]))) return false;
    }
    return true;
}

int main()
{
    while (~scanf("%d",&n))
    {
        if (n==-1) break;
        m=4*n+1;
        rep(i,0,m)
            rep(j,0,m) dis[i][j]=1000000;
        rep(i,0,m) dis[i][i]=0;
        s[0]=point(0,5);
        rep(i,1,n)
        {
            scanf("%lf",&x);
            rep(j,1,4)
                {
                    scanf("%lf",&y);
                    s[4*(i-1)+j]=point(x,y);
                }

        }
        s[m]=point(10,5);
        rep(i,0,m)
            rep(j,i+1,m)
                if (ok(i,j)) dis[i][j]=dist(s[i],s[j]);
        rep(i,0,m)
            rep(j,0,m)
                rep(k,0,m)
                    dis[j][k]=min(dis[j][k],dis[j][i]+dis[i][k]);
        printf("%.2f\n",dis[0][m]);
    }
}
时间: 2024-10-15 19:12:38

poj 1556 题解的相关文章

POJ 1556

枚举每两点的直线,看连线中是否存在线段交点,若存在,即这两点的直线不存在.建图,DIJK就可以了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 8 const int Max=100; 9 const int M=3000; 10 c

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 1556 - The Doors 线段相交不含端点

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

最短路+线段交 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

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 zoj1721 BellmanFord 最短路+判断直线相交

http://poj.org/problem?id=1556 The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6120   Accepted: 2455 Description You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will a

POJ 2263 POJ 1556

2263 题目意思是求起点城市到终点城市的途径中的最大载重量,可以用Dijkstra或者floyd 来解决,我是用的floyd 感觉更直观 因为只需要将递推式改成w[i][j] = Max(w[i][j],Min(w[i][k],w[k][j]));便可得到答案,而且floyd写法比较简单但是复杂度为n的3次方,不过此题还是能AC Source Code Problem: 2263 User: lyz963254 Memory: 760K Time: 32MS Language: G++ Res

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 - 3641 题解

题意:检验一个数是否是质数,且满足ap = a (mod p) 题解:快速幂,质数检验 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 long long power(long long a,long long b,long long c) 7 { 8 long long res,t; 9 res=