这道题一定要好好纪念一下,改代码改了一整天。。。。
代码写出来后一直WA,原来以为是精度问题或者程序哪个地方出了点小错误,毕竟第一次写排序增量算法
然后一直在改,后来实在找不出了,去看了discuss,有人说把g++改成c++就过了
然后自己也试了一遍,就过了。。。。
后来搜了下g++和c++的区别,得知g++输出浮点数时最好用%f,要不然有时候会出错。
然后把输出改成了%f,用g++提交,过了。。。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
const double eps=1e-8;
struct Point {
double x,y;
Point(){};
Point(double xx,double yy) {
x=xx; y=yy;
}
double operator ^(const Point b) const {
return x*b.y-y*b.x;
}
double operator *(const Point b) const {
return x*b.x+y*b.y;
}
};
struct Line {
Point s,e;
double angle;
};
int n,m,ln,order[1505],dq[1505],bot,top;
Point p[1505];
Line l[1505];
double multi(Point p,Point a,Point b) {//点b在直线p-a的左边时值>0
return (a.x-p.x)*(b.y-p.y)-(a.y-p.y)*(b.x-p.x);
}
int dblcmp(double a) {
if (fabs(a)<eps) return 0;
return a>0?1:-1;
}
//按极角从小到大排序
//对于相同角度的两个半平面(a1a2,b1b2),只需要保留被其他角度相同的半平面覆盖的那一个
int cmp(int a,int b) {
int d=dblcmp(l[a].angle-l[b].angle);
if (!d) return dblcmp(multi(l[a].s,l[b].s,l[b].e))<0;
return d<0;
}
int EqualPoint(Point a, Point b) {//两点相等
return dblcmp(a.x - b.x) == 0 && dblcmp(a.y - b.y) == 0;
}
void AddLine(Point s,Point e){
l[ln].s=s;
l[ln].e=e;
l[ln].angle=atan2(e.y-s.y,e.x-s.x);
order[ln]=ln;
ln++;
}
Point Intersect(Line l1,Line l2) {
/*double s1,s2;
s1=multi(a.s,a.e,b.s);
s2=multi(a.s,a.e,b.e);
return Point((a.s.x*s2+a.e.x*s1)/(s1+s2),(a.s.y*s2+a.e.y*s1)/(s1+s2));*/
double dot1, dot2;
Point p;
dot1 = multi(l2.s, l1.e, l1.s);
dot2 = multi(l1.e, l2.e, l1.s);
p.x = (l2.s.x * dot2 + l2.e.x * dot1) / (dot2 + dot1);
p.y = (l2.s.y * dot2 + l2.e.y * dot1) / (dot2 + dot1);
return p;
}
int Judge(Line l0,Line l1,Line l2) {
Point p=Intersect(l1,l2);
return dblcmp(multi(l0.s,l0.e,p))>0;//因为该题是顺时针给出的点,所以p在直线左边即<0时,top--
}
void HPI(){
int i,j;
sort(order,order+ln,cmp);
for(i=1,j=0;i<n;i++) {
if (dblcmp(l[order[i]].angle-l[order[j]].angle)>0) order[++j]=order[i];
ln=j+1;
}
dq[0]=order[0];
dq[1]=order[1];
bot=0,top=1;
for( i=2;i<ln;i++) {
while(bot<top && Judge(l[order[i]],l[dq[top-1]],l[dq[top]]))
top--;
while(bot<top && Judge(l[order[i]],l[dq[bot+1]],l[dq[bot]]))
bot++;
dq[++top]=order[i];
}
//对最后加进去的点后进行处理
while(bot<top && Judge(l[dq[bot]],l[dq[top-1]],l[dq[top]])) top--;
while(bot<top && Judge(l[dq[top]],l[dq[bot+1]],l[dq[bot]])) bot++;
//printf("%d %d\n",bot,top);
m=0;
if (top<=bot+1) return;//不能构成封闭的多边形
//最终的核即各线段所在直线的交点
for( i=bot;i<top;i++) p[m++]=Intersect(l[dq[i]],l[dq[i+1]]);
if (top>bot+1) p[m++]=Intersect(l[dq[bot]],l[dq[top]]);//即最终的线段大于2条,可形成环时
m=unique(p,p+m,EqualPoint)-p;
}
double xmul(Point p0,Point p1,Point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int T,i;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
ln=0;
memset(dq,0,sizeof(dq));
memset(order,0,sizeof(order));
double s=0;
for(i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
/*for(inti=0;i<n;i++) s+=p[i]^p[(i+1)%n];
if (s>0){
for(int i=0;i<n/2;i++) swap(p[i],p[n-1-i]);
}
*/
p[n]=p[0];
for(i=0;i<n;i++) AddLine(p[i],p[i+1]);
HPI();
s=0;
for(i=0;i<m;i++) {
s+=p[i]^p[(i+1)%m];
}
if (fabs(s)<eps) s=0.0;
printf("%.2lf\n",fabs(s/2.0));
}
return 0;
}