半平面交 poj1279 3335 3130

POJ 1279 半平面交 求多边形的核

今天找了好久,没找到传说中的N*LOG N 的求法。后来看了别篇求多边形交的代码没看懂,明天再接再历吧。

POJ 3335 求多边形是否存在核

这题原来用1279 判断面积是否为0 WA 了,后来判断核的顶点数是否为0 AC。

POJ 3130 同上

这题将原来的求面积的公式改动一点。一个小错找了大半个下午。感叹几何的精度问题太难以掌握了。需要自己对其中的每一段模板的细节都熟悉透彻,一点含糊就会WA。


图片

        Source Code

Problem: 1279 User: liu696639
Memory: 464K Time: 79MS
Language: C++ Result: Accepted

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=3005;
const double EP=1e-10; 
struct POINT 
{
       double x,y;
};
struct POLY
{
     POINT p

--;

     int pn;

} ;
struct LINE           // 直线的解析方程 a*x+b*y+c=0  为统一表示,约定 a >= 0 

   double a; 
   double b; 
   double c; 
   LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;} 
}; 
double multiply(POINT p1,POINT p2,POINT p0)
{
       return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool samepoint(POINT p1,POINT p2) 
{
     if(p1.x!=p2.x)return false;
     if(p1.y!=p2.y)return false;
     return true; 
}

LINE getline(POINT p1,POINT p2)
{
     LINE temp;
     temp.a=p2.y-p1.y;
     temp.b=p1.x-p2.x;
     temp.c=p2.x*p1.y-p1.x*p2.y;
     return temp;
}
POINT linecross(LINE ln1,LINE ln2)
{
     POINT temp;
     double a1=ln1.a;
     double b1=ln1.b;
     double c1=ln1.c;
     double a2=ln2.a;
     double b2=ln2.b;
     double c2=ln2.c;
     if(fabs(b1)<EP) 
     {
          temp.x=-c1/a1;
          temp.y=(-c2-a2*temp.x)/b2;
     }
     else 
     {
          temp.x=(c1 * b2 - b1 * c2) / (b1 * a2 - b2 * a1);
          temp.y=(-c1-a1*temp.x)/b1;
     }
     return temp;
}
POLY cutpol(POINT p1,POINT p2,POLY pol)
{
    POLY npol;
    POINT inp;
    LINE ln1,ln2;
    double cp1,cp2;
    npol.pn=0;
    for(int i=0;i<pol.pn;i++)
    {
        cp1=multiply(p2,pol.p[i],p1);
        cp2=multiply(p2,pol.p[i+1],p1);
        if(fabs(cp1)<EP||fabs(cp2)<EP)
        {
            if(fabs(cp1)<EP)npol.p[npol.pn++]=pol.p[i];
            if(fabs(cp2)<EP)npol.p[npol.pn++]=pol.p[i+1];
        }
        else if(cp1<0 && cp2<0)
        {
            npol.p[npol.pn++]=pol.p[i];
            npol.p[npol.pn++]=pol.p[i+1];
        }
        else if(cp1*cp2<0)
        {
            ln1=getline(p1,p2);
            ln2=getline(pol.p[i],pol.p[i+1]);
            inp=linecross(ln1,ln2);
            if(cp1<0)
            {
                npol.p[npol.pn++]=pol.p[i];
                npol.p[npol.pn++]=inp;
            }
            else 
            {
                npol.p[npol.pn++]=inp;
                npol.p[npol.pn++]=pol.p[i+1];
            }
        }
    }
    pol.pn=0;
    if(npol.pn==0)return pol;
    pol.p[pol.pn++]=npol.p[0];
    for( int i=1;i<npol.pn;i++) //去掉重边 
        if( !samepoint(npol.p[i],npol.p[i-1]))
            pol.p[pol.pn++]=npol.p[i];
    if( pol.pn!=1 && samepoint(pol.p[pol.pn-1],pol.p[0])) //重要处理 
        pol.pn--;
    pol.p[pol.pn]=pol.p[0];//多边形加个顶点使其封闭
    return pol;
}

void reclock(POINT pol[],int pn) 
{
    POINT temp;
    for(int i=0;i<(pn-1)/2;i++)
    {
        temp=pol[i];
        pol[i]=pol[pn-1-i];
        pol[pn-1-i]=temp;
    }
}
double area_of_polygon(int len,POINT point[])
{
    double area=0;
    for(int i=1;i<=len;i++)
            area+=multiply(point[0],point[i-1],point[i%len]);
    return area/2.0; 
}
int main()

     int cas;
     POLY pol;
     scanf("%d",&cas);
     for(int i=0;i<cas;i++)
     {
          scanf("%d",&pol.pn);
          for(int j=0;j<pol.pn;j++)
             scanf("%lf%lf",&pol.p[j].x,&pol.p[j].y);
          //先输入pol多边形的每条边 从(0->pn-1)。
if(area_of_polygon(pol.pn,pol.p)>0)reclock(pol.p,pol.pn);
pol.p[pol.pn]=pol.p[0]; //多边形加个顶点使其封闭 
POLY npol=pol; 
for(int i=0;i<pol.pn;i++)// 
npol=cutpol(pol.p[i],pol.p[i+1],npol); //枚举pol的每条边去切割, npol得一个新的npol
//得到的npol为所要求的多边形的核  此时pol.pn不变,只在pol.p[pn]有个中间点

          double area=area_of_polygon(npol.pn,npol.p);
          printf("%.2lf\n",fabs(area));
     }
     return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值