hdu 1454- Pipe-解析几何

Pipe

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 251    Accepted Submission(s): 104


Problem 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 the company ran into the problem of determining how far the light can reach inside each component of the pipe. Note that the material which the pipe is made from is not transparent and not light reflecting.

hdu 1454- Pipe-解析几何_第1张图片

Each pipe component consists of many straight pipes connected tightly together. For the programming purposes, the company developed the description of each component as a sequence of points [x1; y1], [x2; y2], . . ., [xn; yn], where x1 < x2 < . . . xn . These are the upper points of the pipe contour. The bottom points of the pipe contour consist of points with y-coordinate decreased by 1. To each upper point [xi; yi] there is a corresponding bottom point [xi; (yi)-1] (see picture above). The company wants to find, for each pipe component, the point with maximal x-coordinate that the light will reach. The light is emitted by a segment source with endpoints [x1; (y1)-1] and [x1; y1] (endpoints are emitting light too). Assume that the light is not bent at the pipe bent points and the bent points do not stop the light beam.

 

Input
The input file contains several blocks each describing one pipe component. Each block starts with the number of bent points 2 <= n <= 20 on separate line. Each of the next n lines contains a pair of real values xi, yi separated by space. The last block is denoted with n = 0.
 

Output
The output file contains lines corresponding to blocks in input file. To each block in the input file there is one line in the output file. Each such line contains either a real value, written with precision of two decimal places, or the message Through all the pipe.. The real value is the desired maximal x-coordinate of the point where the light can reach from the source for corresponding pipe component. If this value equals to xn, then the message Through all the pipe. will appear in the output file.
 

Sample Input
     
     
     
     
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 0
 

Sample Output
     
     
     
     
4.67 Through all the pipe.
 

Source
ACM暑期集训队练习赛(七)
 

Recommend
lcy

题意:
题目的意思是给定线段的两个端点的坐标,判断同一组的几条线段是否相交,是就yes,不是就no。

知识点:
我们分两步确定两条线段是否相交:
(1)快速排斥试验
设以线段 P1P2 为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,
如果R和T不相交,显然两线段不会相交。
(2)跨立试验
如果两线段相交,则两线段必然相互跨立对方。
若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,
即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。
上式可改写成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。
当 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,
但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;
同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。
所以判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。
同理判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAX 100+5
typedef long long LL;
const double pi=3.141592653589793;
const int INF=1e9;
const double inf=1e20;
const double eps=1e-6;
const int mod=1000000007;
struct point
{
    int x,y;
} p[35][105];
double circulation(point a,point b,point c)///计算向量BA、CA的叉积
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
bool cross(point a,point b,point c,point d)///判断线段AB和CD是否相交
{
    if(max(a.x,b.x)>=min(c.x,d.x)&&///快速排斥试验
            max(c.x,d.x)>=min(a.x,b.x)&&
            max(a.y,b.y)>=min(c.y,d.y)&&
            max(c.y,d.y)>=min(a.y,b.y)&&
            circulation(a,b,c)*circulation(a,d,b)>=0&&///跨立试验
            circulation(c,a,d)*circulation(c,d,b)>=0)
        return true;
    return false;
}
int main()
{
    int n,k[35];
    while(cin>>n)///n表示管道的数目
    {
        memset(k,0,sizeof(k));
        memset(p,0,sizeof(p));
        for(int i=0; i<n; i++)
        {
            cin>>k[i];///i表示是第i条管道,k[i]表示这条管道是由k[i]个端点组成
            for(int j=0; j<k[i]; j++)
                scanf("%d%d",&p[i][j].x,&p[i][j].y);
        }
        if(n==1)
        {
            printf("No\n");
            continue;
        }
        int flag=0;
        for(int i=0; i<n-1; i++)///枚举每条折线段上的每段线段
                        ///判断其是否与其它折线段的线段相交
            for(int j=1; j<k[i]; j++)
                for(int t=i+1; t<n; t++)
                    for(int h=1; h<k[t]; h++)
                        if(cross(p[i][j-1],p[i][j],p[t][h-1],p[t][h]))
                        {
                            flag=1;
                            break;
                        }
        if(flag) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


你可能感兴趣的:(算法,线段相交,hduoj,解析几何)