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;
}