hdu-1154 Cutting a Polygon(计算几何综合应用,多模板)

题目链接:点击打开链接

Cutting a Polygon

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


Problem Description
Given is a simple but not necessarily convex polygon. Given is also a line in the plane. If the polygon is cut along the line then we may get several smaller polygons. Your task is to find the length of the cut, that is the total length of the segments in the intersection of the line and the polygon. 
 

Input
Input consists of a number of cases. The data of each case appears on a number of input lines, the first of which contains two non negative integers n and m giving the number of the vertices of the polygon and the number of cutting lines to consider, 3 ≤ n ≤ 1000. The following n lines contain coordinates of the vertices of the polygon; each line contains the x and y coordinates of a vertex. The vertices are given either in clockwise or counterclockwise order. Each of the following m lines of input contains four numbers; these are x and y coordinates of the two points defining the cutting line. If a vertex of the polygon is closer than 10e-8 to the cutting line then we consider that the vertex lies on the cutting line. 
Input is terminated by a line with n and m equal to 0. 

 

Output
For each cutting line, print the total length of the segments in the intersection of the line and the polygon defined for this test case, with 3 digits after the decimal point. Note: the perimiter of a polygon belongs the polygon. 
The picture above illustrates the first cutting line for the polygon from the sample. 
 

Sample Input
   
   
   
   
9 5 0 0 0 2 1 1 2 2 3 1 4 2 5 1 6 2 6 0 -1 2 7.5 1 0 1 6 1 0 1.5 6 1.5 0 2 6 1 0 0 0 2 0 0
 

Sample Output
   
   
   
   
2.798 6.000 3.000 2.954 2.000
题意:求直线与多边形的公共长度。

思路:详细请看代码注释

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 1010
#define eps 1e-8
struct Node
{
    double x,y;
} p[N],q[N*10];
int n;
bool cmp(Node a,Node b)//排序,从左到右,从下到上
{
    if(abs(a.x-b.x)<eps)
        return a.y<b.y;
    return a.x<b.x;
}
double dist(Node a,Node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double mulit(Node a,Node c,Node b)//向量ac与向量ab叉乘
{
    return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x);
}
int check(Node a,Node b,Node c,Node d)//判断直线ab与线段cd是否相交
{
    if(mulit(a,c,b)*mulit(a,d,b)<=0)
        return 1;
    return 0;
}
Node get_point(Node a,Node b,Node c,Node d)//求直线ab与线段cd的交点(已证明直线与线段相交,则可以当做两直线)
{
    Node ret=a;
    double t=((a.x-c.x)*(c.y-d.y)-(a.y-c.y)*(c.x-d.x))
             /((a.x-b.x)*(c.y-d.y)-(a.y-b.y)*(c.x-d.x));
    ret.x+=(b.x-a.x)*t;
    ret.y+=(b.y-a.y)*t;
    return ret;
}
int checkss(Node a,Node c,Node d)//判断点a是否在线段cd上
{
    if(mulit(a,c,d)!=0)
        return 0;
    if((a.x<c.x&&a.x<d.x)||(a.x>c.x&&a.x>d.x))
        return 0;
    if((a.y<c.y&&a.y<d.y)||(a.y>c.y&&a.y>d.y))
        return 0;
        return 1;
}
int isI(Node a,Node b,Node c,Node d)//判断线段ab和线段cd是否相交(互跨)
{
    if(mulit(a,c,b)*mulit(a,d,b)<=0&&mulit(c,a,d)*mulit(c,b,d)<=0)
        return 1;
    return 0;
}
int checks(Node a)//判断点a是否在多边形内
{
    Node b=a,c,d;
    b.x=1e15;
    int num=0;
    for(int i=0;i<n;i++)
    {
        c=p[i];
        d=p[i+1];
        if(checkss(a,c,d))
            return 1;
        if(abs(c.y-d.y)<eps)
            continue;
        if(checkss(c,a,b))
        {
            if(c.y>d.y)
                num++;
        }
        else if(checkss(d,a,b))
        {
            if(d.y>c.y)
                num++;
        }
        else if(isI(a,b,c,d))
        {
            num++;
        }
    }
    return num%2;
}
double get_len(Node a,Node b)//求直线与多边形的公共面积
{
    Node c,d;
    int cnt=0;
    for(int i=0; i<n; i++) //求出直线与多边形各边的交点
    {
        c=p[i];
        d=p[i+1];
        if(abs(mulit(a,b,c))<eps&&abs(mulit(a,b,d))<eps)
        {
            q[cnt++]=c;
            q[cnt++]=d;
        }
        else if(check(a,b,c,d))
            q[cnt++]=get_point(a,b,c,d);
    }
    if(cnt==0)
        return 0.0;
    sort(q,q+cnt,cmp);
    int t=1;
    for(int i=1; i<cnt; i++)
    {
        c=q[i];
        d=q[i-1];
        if(!(abs(c.x-d.x)<eps&&abs(c.y-d.y)<eps))
            q[t++]=q[i];
    }//去重
    double sum=0.0;
    for(int i=1; i<t; i++)
    {
        c.x=(q[i].x+q[i-1].x)*0.5;
        c.y=(q[i].y+q[i-1].y)*0.5;
        if(checks(c))
                sum+=dist(q[i],q[i-1]);
    }
    return sum;
}
int main()
{
    int m;
    Node a,b;
    while(~scanf("%d %d",&n,&m)&&n&&m)
    {
        for(int i=0; i<n; i++)
            scanf("%lf %lf",&p[i].x,&p[i].y);
        p[n]=p[0];
        for(int i=0; i<m; i++)
        {
            scanf("%lf %lf %lf %lf",&a.x,&a.y,&b.x,&b.y);
            printf("%.3lf\n",get_len(a,b));
        }
    }
    return 0;
}


你可能感兴趣的:(ACM,HDU)