poj1039(计算几何)线段相交

题意:给一个管道求光线能穿到的最大x坐标。

解法:通过旋转光线一定可以使得光线接触一个上点和一个下点。枚举接触的上下点,然后逐一判断光线是否穿过每个拐点面。碰到一个拐点面没有穿过的,则是因为与其左边线段相交,求出直线与线段交点更新答案即可。不想交则说明在前一个拐点已经穿出去了。

代码:

/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-10
const double pi=acos(-1.0);
typedef long long LL;
const int Max=10100;
const int INF=1000000007;
struct point
{
    double x,y;
} points1[30],points2[30];
int n;
int mult(point a,point b,point c)
{
    a.x-=c.x;
    a.y-=c.y;
    b.x-=c.x;
    b.y-=c.y;
    double tool=a.x*b.y-a.y*b.x;
    if(abs(tool)<=eps)
        return 0;
    if(tool<0)
        return -1;
    return 1;
}
double mult2(point a,point b,point c)
{
    a.x-=c.x;
    a.y-=c.y;
    b.x-=c.x;
    b.y-=c.y;
    return a.x*b.y-a.y*b.x;
}
bool OK(point p1,point p2,int i)
{
    return mult(p1,p2,points1[i])*mult(p1,p2,points2[i])<=0;
}

bool inter(point p1,point p2,point p3,point p4)
{
    if(mult(p1,p2,p3)*mult(p1,p2,p4)<0)
        return true;
    return false;
}
double getx(point p1,point p2,point p3,point p4)
{
    double area1=abs(mult2(p1,p2,p3)),area2=abs(mult2(p1,p2,p4));
    return area1/(area1+area2)*p4.x+area2/(area1+area2)*p3.x;
}
double solve(point p1,point p2)
{
    if(!OK(p1,p2,0))
        return points1[0].x;
    for(int i=1; i<n; i++)
    {
        if(!OK(p1,p2,i))
        {
            if(inter(p1,p2,points1[i-1],points1[i]))
                return getx(p1,p2,points1[i-1],points1[i]);
            if(inter(p1,p2,points2[i-1],points2[i]))
                return getx(p1,p2,points2[i-1],points2[i]);
            return points1[i-1].x;
        }
    }
    return points1[n-1].x;
}
int main()
{
    while(scanf("%d",&n)==1&&n)
    {
        for(int i=0; i<n; i++)
        {
            scanf("%lf%lf",&points1[i].x,&points1[i].y);
            points2[i].x=points1[i].x;
            points2[i].y=points1[i].y-1.0;
        }
        double ans=points1[0].x;
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
            {
                if(i==j)continue;
                ans=max(ans,solve(points1[i],points2[j]));//cout<<i<<" "<<j<<" "<<solve(points1[i],points2[j])<<endl;
            }
        if(abs(ans-points1[n-1].x)<eps)
            printf("Through all the pipe.\n");
        else
            printf("%.2f\n",ans);
    }
    return 0;
}
/*
4
0 1
1 2
2 1
3 -1
4
-301 1
-254 8
-196 3
-52 13
4
0 1
2 2
4 1
6 4
6
0 1
2 -0.6
5 -4.45
7 -5.57
12 -10.8
17 -16.55
*/

poj1039(计算几何)线段相交

时间: 2024-10-13 12:36:56

poj1039(计算几何)线段相交的相关文章

德莱联盟 计算几何 线段相交

难度:1 描述 欢迎来到德莱联盟.... 德莱文... 德莱文在逃跑,卡兹克在追.... 我们知道德莱文的起点和终点坐标,我们也知道卡兹克的起点和 终点坐标,问:卡兹克有可能和德莱文相遇吗?,并且保证他们走的都是直线. 输入 几组数据,一个整数T表示T组数据每组数据 8个实数,分别表示德莱文的起点和终点坐标,以及卡兹克的起点和终点坐标 输出 如果可能 输出 Interseetion,否则输出 Not Interseetion 样例输入 2 -19.74 7.14 22.23 -27.45 -38

POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)

That Nice Euler Circuit Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 1977   Accepted: 626 Description Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his primary school Joey heard about

POJ 3347 Kadj Squares (计算几何+线段相交)

题意:从左至右给你n个正方形的边长,接着这些正方形都按照旋转45度以一角为底放置坐标轴上,最左边的正方形左端点抵住y轴,后面的正方形依次紧贴前面所有正方形放置,问从上方向下看去,有哪些正方形是可以被看到的(如图) 题解:首先我们找到每个正方形左右端点的坐标转化为一条线段,接着我们寻找哪些线段被其他某些条线段覆盖,这些被覆盖的线段就不能被看到 寻找被覆盖的线段利用区贪心间,我们按照左端点升序.左端点相同右端点降序排序,则左端点一定被前面的线段覆盖,接着对于右端点使用单调栈的思想寻找可以看到的线段就

poj1039——计算几何 求直线与线段交点,判断两条直线是否相交

poj1039——计算几何  求直线与线段交点,判断两条直线是否相交 Pipe Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9439   Accepted: 2854 Description The GX Light Pipeline Company started to prepare bent pipes for the new transgalactic light pipeline. During the de

POJ 3304 Segments(计算几何:直线与线段相交)

POJ 3304 Segments 大意:给你一些线段,找出一条直线能够穿过所有的线段,相交包括端点. 思路:遍历所有的端点,取两个点形成直线,判断直线是否与所有线段相交,如果存在这样的直线,输出Yes,但是注意去重. struct Point { double x, y; } P[210]; struct Line { Point a, b; } L[110]; double xmult(Point p1, Point p2, Point p) { return (p1.x-p.x)*(p2.

Pick-up sticks(计算几何_线段相交)

Description Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to find the top sticks, that is these sticks such that there is no stick on top of them. Stan has noticed

【TOJ 1288】计算几何练习题――线段相交(模板题)

描述 线段相交测试在计算几何中是经常用到的,给定线段P1P2(P1和P2是线段的两端点,且不重合).P3P4(P3和P4是线段的两端点,且不重合),判断P1P2和P3P4是否相交.P1P2和P3P4不重合,即指只存在一个点P,它既落在P1P2上又落在P3P4上(含线段的端点). 输入 输入数据有多组,第一行为测试数据的组数N,下面包括2N行,每组测试数据含2行,第一行为P1P2的坐标值,第二行为P3P4的坐标值,比如下面的数据10 0 1 12 2 3 3表示P1.P2.P3.P4的坐标分别为:

poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)

Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are

【计算几何】线段相交

问题描述:已知两条线段P1P2和Q1Q2,判断P1P2和Q1Q2是否相交,若相交,求出交点. 两条线段的位置关系可以分为三类:有重合部分.无重合部分但有交点.无交点. 算法的步骤如下: 1.快速排斥实验. 设以线段P1P2为对角线的矩形为R,设以线段Q1Q2为对角线的矩形为T,如果R和T不相交,则两线段不相交. 2.跨立实验. 如果两线段相交,则两线段必然相互跨立对方. 若P1P2跨立Q1Q2,则矢量(P1-Q1)和(P2-Q1)位于矢量(Q2-Q1)的两侧,即( P1 - Q1 ) × ( Q