POJ - 1039 Pipe(计算几何)

http://poj.org/problem?id=1039

题意

有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道。

分析

最远的直线必定经过一个上折点和一个下折点。枚举这两个点即可。

#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;
    }
    void input()
    {
        scanf("%lf%lf",&x,&y);
    }
};
struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;e = _e;
    }
    //两直线相交求交点
    //第一个值为0表示直线重合,为1表示平行,为0表示相交,为2是相交
    //只有第一个值为2时,交点才有意义
    pair<int,Point> operator &(const Line &b)const
    {
        Point res = s;
        if(sgn((s-e)^(b.s-b.e)) == 0)
        {
            if(sgn((s-b.e)^(b.s-b.e)) == 0)
                return make_pair(0,res);//重合
            else return make_pair(1,res);//平行
        }
        double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x += (e.x-s.x)*t;
        res.y += (e.y-s.y)*t;
        return make_pair(2,res);
    }
};
//判断直线和线段相交
bool Seg_inter_line(Line l1,Line l2) //判断直线l1和线段l2是否相交
{
    return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0;
}

Point up[100],down[100];
int main()
{
    int n;
    while(scanf("%d",&n) == 1 && n)
    {
        for(int i = 0;i < n;i++)
        {
            up[i].input();
            down[i] = up[i];
            down[i].y -= 1;
        }
        bool flag = false;//穿过所有的标记
        double ans = -10000000.0;
        int k;
        for(int i = 0;i < n;i++)
        {
            for(int j = 0;j < n;j++)
            {
                for(k = 0;k < n;k++) //直线L最大延伸到第k-1节管子
                    if(Seg_inter_line(Line(up[i],down[j]),Line(up[k],down[k])) == false)
                        break;
                if(k >= n)
                {
                    flag = true;
                    break;
                }
                if(k > max(i,j)) //由于不清楚L究竟是与第k-1节管子的上管壁还是下管壁相交,因此都计算交点,取最优
                {
                    if(Seg_inter_line(Line(up[i],down[j]),Line(up[k-1],up[k])))
                    {
                        pair<int,Point>pr = Line(up[i],down[j])&Line(up[k-1],up[k]);
                        Point p = pr.second;
                        ans = max(ans,p.x);
                    }
                    if(Seg_inter_line(Line(up[i],down[j]),Line(down[k-1],down[k])))
                    {
                        pair<int,Point>pr = Line(up[i],down[j])&Line(down[k-1],down[k]);
                        Point p = pr.second;
                        ans = max(ans,p.x);
                    }
                }
            }
            if(flag)break;
        }
        if(flag)printf("Through all the pipe.\n");
        else printf("%.2lf\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/fht-litost/p/9349840.html

时间: 2024-08-07 22:03:20

POJ - 1039 Pipe(计算几何)的相关文章

poj 1039 Pipe (计算几何)

Pipe Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9110   Accepted: 2755 Description The GX Light Pipeline Company started to prepare bent pipes for the new transgalactic light pipeline. During the design phase of the new pipe shape th

poj 1039 Pipe(几何基础)

Pipe Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9932   Accepted: 3045 Description The GX Light Pipeline Company started to prepare bent pipes for the new transgalactic light pipeline. During the design phase of the new pipe shape th

简单几何(直线与线段相交) POJ 1039 Pipe

题目传送门 题意:一根管道,有光源从入口发射,问光源最远到达的地方. 分析:黑书上的例题,解法是枚举任意的一个上顶点和一个下顶点(优化后),组成直线,如果直线与所有竖直线段有交点,则表示能穿过管道. /************************************************ * Author :Running_Time * Created Time :2015/10/31 星期六 10:28:12 * File Name :POJ_1039.cpp ***********

POJ 1039 Pipe 枚举线段相交

Pipe Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9493   Accepted: 2877 Description The GX Light Pipeline Company started to prepare bent pipes for the new transgalactic light pipeline. During the design phase of the new pipe shape th

POJ 1039 Pipe

题意:一根管子,中间有一些拐点,给出拐点的上坐标,下坐标为上坐标的纵坐标减1,管子不能透过光线也不能折射光线,问光线能射到最远的点的横坐标. 解法:光线射到最远处的时候一定最少经过两个拐点,枚举每两个顶点,判断最远光线射到的位置.代码姿势不够优美……都是眼泪啊 代码: #include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h&g

POJ 1039

一条直线,必定可以通过旋转和平移使得它和一个上顶点一下顶点相切,这样的直线是最优的.因为这样能确定了直线所能到达的最远X.这样的两个顶点就规定了它的上下界, 所以,枚举上下顶点,注意判断是否能到达入口处.只需判断直线是否与每个横切面的直线都有相交. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using

Pipe - POJ 1039(线段相交交点)

题目大意:有一个不反光并且不透光的管道,现在有一束光线从最左端进入,问能达到的最右端是多少,输出x坐标. 分析:刚开始做是直接枚举两个点然后和管道进行相交查询,不过这样做需要考虑的太多,细节不容易掌控.后来发现其实只需要对接口进行一下相交查询就简单多了,因为只需要考虑能不能通过每个截口就可以了,而且这样做的好处还有没有平行线和重叠线的情况,因为所有的截口都是垂直于x轴的,换一种想法海阔太空啊. 代码如下: =============================================

POJ Transmitters(计算几何 极角排序啊)

题目链接:http://poj.org/problem?id=1106 Description In a wireless network with multiple transmitters sending on the same frequencies, it is often a requirement that signals don't overlap, or at least that they don't conflict. One way of accomplishing thi

POJ 1039 直线和线段相交

题意: 题意很好理解,从左边射过来的光线,最远能经过管道到右边多少距离. 分析: 光线一定经过一个上端点和一个下端点,这一点很容易想到.然后枚举上下端点即可 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define eps 1e-8 #define INF 1e9 #define OK sgn(tmp