【题目描述】
Remmarguts公主成功地解决了象棋问题。作为奖励,Uyuw计划举办一场音乐会,地点是以其伟大的设计师Ihsnayish命名的巨大广场。
这个位于自由三角洲联合王国(UDF,United Delta of Freedom)最繁华地带的广场是一个坐标范围[0,10000]*[0,10000]的正方形。有一些长椅已经固定在广场上许多年了,但是杂乱无章。见下图:
我们有三张长椅,并且观众面对的方向已经用箭头画出。这些椅子年代久远,并且沉重得无法移动。Remmarguts公主让广场现在的主人UW先生在广场上修建一个大的舞台。这个舞台应当尽可能大,但必须确保在任意长椅上任意位置的观众不必转身就能看到舞台(也就是说舞台必须在长椅所在直线的观众朝向那一侧)。
为了简化问题,舞台的高度可以任意高来确保只要你面向舞台所在的那一侧,你就能看到舞台上的歌唱家/画家——Uyuw,即使你的面前有数千张长椅。
作为一名脑残粉,你能告诉他们舞台的最大面积吗?
【输入格式】
输入包含不超过10组数据。
每组数据格式如下:
第一行有一个整数N(N<=20000),代表长椅的数量。
接下来有N行,每行有4个整数x1,y1,x2,y2,代表一张长椅。这张长椅是以(x1,y1)和(x2,y2)为端点的线段,并且面向其左侧。一个点(x,y)在线段左侧是指(x-x1)*(y-y2)-(x-x2)*(y-y1)>=0.
【输出格式】
对每组数据输出一个一个实数,即舞台的最大面积。精确到1位小数。你的答案被认为是正确的当且仅当它与标准答案之差小于0.2。
【样例输入】
3
10000 10000 0 5000
10000 5000 5000 10000
0 5000 5000 0
【样例输出】
54166666.7
【提示】
样例如下:
建议你采用Pascal中的Extended类型或者C/C++中的long double类型来避免精度误差。不过标程仅仅用了double。
半平面交模板(太坑了)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 typedef double ld; 8 struct point 9 { 10 ld x,y; 11 point(){} 12 point(ld _x,ld _y) {x=_x,y=_y;} 13 }p[30001]; 14 struct Line 15 { 16 point a,b; 17 ld angle; 18 Line(){} 19 Line(point _a,point _b) {a=_a,b=_b;} 20 }line[30001],sta[300001]; 21 ld eps=1e-10,ans; 22 int n,cnt; 23 point operator -(point a,point b) 24 { 25 return point(a.x-b.x,a.y-b.y); 26 } 27 int dcmp(ld x) 28 { 29 if (x>eps) return 1; 30 if (x<-eps) return -1; 31 return 0; 32 } 33 ld cross(point a,point b) 34 { 35 return a.x*b.y-a.y*b.x; 36 } 37 ld getangle(Line l) 38 { 39 return atan2(l.b.y-l.a.y,l.b.x-l.a.x); 40 } 41 point inter(Line u,Line v) 42 { 43 double k1=(cross((u.b-v.a),(v.b-v.a))); 44 double k2=(cross((v.b-v.a),(u.a-v.a))); 45 double t=k1/(k1+k2); 46 return point(u.b.x+(u.a.x-u.b.x)*t,u.b.y+(u.a.y-u.b.y)*t); 47 } 48 bool cmp(Line u,Line v) 49 { 50 int t=dcmp(u.angle-v.angle); 51 if (t) return t<0; 52 return dcmp(cross(u.a-v.b,v.a-v.b))>0; 53 } 54 bool judge(Line a,Line b,Line c) 55 { 56 point p=inter(b,c); 57 return dcmp(cross(a.a-p,a.b-p))<0; 58 } 59 void HPT() 60 {int i,head,tail; 61 sort(line+1,line+n+1,cmp); 62 int tmp=1; 63 for (i=2;i<=n;i++) 64 if (dcmp(line[i].angle-line[i-1].angle)!=0) 65 line[++tmp]=line[i]; 66 n=tmp; 67 head=1,tail=2; 68 sta[1]=line[1];sta[2]=line[2]; 69 for (i=3;i<=n;i++) 70 { 71 while (tail-1>=head&&judge(line[i],sta[tail],sta[tail-1])) tail--; 72 while (head+1<=tail&&judge(line[i],sta[head+1],sta[head])) head++; 73 tail++; 74 sta[tail]=line[i]; 75 } 76 while (tail-1>=head&&judge(sta[head],sta[tail],sta[tail-1])) tail--; 77 while (head+1<=tail&&judge(sta[tail],sta[head+1],sta[head])) head++; 78 cnt=0; 79 if (tail-head<=1) return; 80 for (i=head;i<tail;i++) 81 { 82 p[++cnt]=inter(sta[i],sta[i+1]); 83 } 84 if (tail>head+1) 85 p[++cnt]=inter(sta[head],sta[tail]); 86 } 87 int main() 88 { 89 int i; 90 while (cin>>n) 91 { 92 n+=4; 93 line[1]=Line(point(0,0),point(10000,0)); 94 line[2]=Line(point(0,10000),point(0,0)); 95 line[3]=Line(point(10000,0),point(10000,10000)); 96 line[4]=Line(point(10000,10000),point(0,10000)); 97 line[1].angle=getangle(line[1]); 98 line[2].angle=getangle(line[2]); 99 line[3].angle=getangle(line[3]); 100 line[4].angle=getangle(line[4]); 101 for (i=5;i<=n;i++) 102 { 103 scanf("%lf%lf%lf%lf",&line[i].a.x,&line[i].a.y,&line[i].b.x,&line[i].b.y); 104 line[i].angle=getangle(line[i]); 105 } 106 HPT(); 107 ans=0; 108 for (i=2;i<cnt;i++) 109 { 110 ans+=cross(p[i]-p[1],p[i+1]-p[1])/2.0; 111 } 112 ans=fabs(ans); 113 printf("%.1lf\n",ans); 114 } 115 return 0; 116 }