1. 程式人生 > >BNU校賽總決賽J 小白兔小灰兔 相交計算幾何模板

BNU校賽總決賽J 小白兔小灰兔 相交計算幾何模板

圖片 coder 描述 spec AC TP 線段 縮小 info

J 小白兔小灰兔

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
Special Judge, 64bit IO Format: %lld

題目描述

老山羊伯伯在地裏收白菜,小白兔和小灰兔看見了就一起來幫忙。

他們幹了半天,終於幹完了。

羊伯伯:小灰兔,這車白菜送給你!

小灰兔:謝謝羊伯伯!

羊伯伯:小白兔,我也送你一車白菜!

小白兔:我不要白菜!給我一包白菜種子吧!

羊伯伯:好!給你~

小白兔:謝謝羊伯伯~

小灰兔把白菜拉到家裏之後,就跟大家夢想中的生活一樣,躺著啥都不幹,吃吃吃,吃了玩~(好想一輩子都這樣啊~小灰兔心想。)

小白兔把種子拿回去,打算開始勤勞地種白菜。然而他發現不是所有土地都能用來種白菜,只有被陽光照到的地方可以種白菜。

小白兔生活的星球可以看作二維平面中的一個簡單多邊形,太陽可以看作一個點。小白兔想知道,這個星球上一共有長度多少的土地可以用來種白菜。

輸入描述:

第一行是一個正整數T(≤ 20),表示測試數據組數,

對於每組測試數據,

第一行是一個整數n(3≤ n≤ 10),表示簡單多邊形的頂點數,

接下來n行,每行是兩個整數xi,yi(-10≤ xi,yi≤10),按照逆時針繞向給出簡單多邊形的n個頂點的坐標,

最後一行是兩個整數x,y(-10≤ x,y≤10),表示太陽的坐標,保證太陽在多邊形外且不在多邊形任意一條邊所在直線上。

輸出描述:

對於每組測試數據,輸出一行,包含一個實數,表示可以用來種白菜的土地的總長度,要求相對誤差不超過技術分享圖片

也就是說,令輸出結果為a,標準答案為b,若滿足技術分享圖片,則輸出結果會被認為是正確答案。

示例1

輸入

2
4
0 0
2 0
2 2
0 2
4 1
4
0 0
2 0
2 2
0 2
4 4

輸出

2.000000000000
4.000000000000

技術分享圖片

技術分享圖片
  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define mod 1000000007
  5
#define INF 0x3f3f3f3f 6 #define LL long long 7 #define pb push_back 8 #define pbk pop_back 9 #define ls(i) (i<<1) 10 #define rs(i) (i<<1|1) 11 #define mp make_pair 12 using namespace std; 13 typedef double db; 14 const int N=5e5+10; 15 const db eps=1e-9; 16 int equzero(db t)//帶精度大小判斷 17 { 18 if(t>eps) return 1; 19 if(t<-eps) return -1; 20 return 0; 21 } 22 struct Point 23 { 24 db x,y; 25 Point(){} 26 Point(db _x,db _y):x(_x),y(_y) {} 27 Point operator +(const Point &b) const //+ 28 { 29 return Point(x+b.x,y+b.y); 30 } 31 Point operator -(const Point &b) const//- 32 { 33 return Point(x-b.x,y-b.y); 34 } 35 Point operator *(const db &b) const// 放大 36 { 37 return Point(x*b,y*b); 38 } 39 Point operator /(const db &b) const//縮小 40 { 41 return Point (x/b,y/b); 42 } 43 db dot(const Point &b) const//點積 44 { 45 return x*b.x+y*b.y; 46 } 47 db det(const Point &b) const//叉積 48 { 49 return x*b.y-b.x*y; 50 } 51 bool operator ==(const Point &b) const 52 { 53 return equzero(x-b.x)==0 && equzero(y-b.y)==0; 54 } 55 bool operator !=(const Point &b) const 56 { 57 return !(Point(x,y)==b); 58 } 59 db mo() // 60 { 61 return sqrt(x*x+y*y); 62 } 63 }pt[N],u,v,mid; 64 struct Line 65 { 66 Point a,b; 67 Line (){} 68 Line (Point _a,Point _b):a(_a),b(_b) {}; 69 bool quickrej(const Line &t) const//快速排斥判斷 70 { 71 return equzero(min(a.x,b.x)-max(t.a.x,t.b.x))<=0 && equzero(min(t.a.x,t.b.x)-max(a.x,b.x))<=0 && equzero(min(a.y,b.y)-max(t.a.y,t.b.y))<=0 && equzero(min(t.a.y,t.b.y)-max(a.y,b.y))<=0; 72 } 73 db len() const 74 { 75 return (b-a).mo(); 76 } 77 bool stra(const Line &t) const //跨立判斷 78 { 79 return equzero((a-t.a).det(t.b-t.a)*(b-t.a).det(t.b-t.a))<0 && equzero((t.a-a).det(b-a)*(t.b-a).det(b-a))<0 ; 80 } 81 bool gfxj(const Line &t) const //規範相交 82 { 83 return quickrej(t) && stra(t); 84 } 85 bool on(const Point &t) const //點在線段上 86 { 87 Line p=Line(a,b); 88 if(p.a.x>p.b.x) 89 swap(p.a,p.b); 90 if(equzero(t.x-p.a.x)<0 || equzero(t.x-p.b.x)>0) 91 return false; 92 if(equzero((p.a-t).det(p.b-t))==0) 93 return true; 94 else 95 return false; 96 } 97 bool kddxj(const Line &t) const //可多點相交 98 { 99 return quickrej(t) && (stra(t) || on(t.a) || on(t.b) || t.on(a) || t.on(b)); 100 } 101 bool para(const Line &t) const // 平行或在一條直線上 102 { 103 return equzero((a.y-b.y)*(t.a.x-t.b.x)-(t.a.y-t.b.y)*(a.x-b.x))==0 ; 104 } 105 db operator & (const Line &t) const //返回切點占直線比例,距a比例 106 { 107 if(equzero((a-b).det(t.a-t.b))==0)return -INF; 108 db tk=((a-t.a).det(t.a-t.b))/((a-b).det(t.a-t.b)); 109 return equzero(tk)>=0 && equzero(tk-1)<=0 ? tk : -INF; 110 } 111 }le[N],lu,lv; 112 int n,m,T; 113 vector<db> cp; 114 db ans,ins,rate; 115 bool flag; 116 int main() 117 { 118 scanf("%d",&T); 119 while(T--) 120 { 121 scanf("%d",&n); 122 for(int i=0;i<=n;i++) 123 scanf("%lf%lf",&pt[i].x,&pt[i].y); 124 for(int i=0;i<n;i++) 125 le[i]=Line(pt[i],pt[(i+1)%n]); 126 ans=0; 127 for(int i=0;i<n;i++) 128 { 129 cp.clear(); 130 for(int j=0;j<n;j++) 131 { 132 ins=le[i]&Line(pt[n],pt[j]); 133 if(ins>=-1) cp.pb(ins); 134 } 135 sort(cp.begin(),cp.end()); 136 rate=0; 137 for(int j=0;j<cp.size()-1;j++) 138 { 139 lu=Line(pt[n],le[i].a+(le[i].b-le[i].a)*((cp[j]+cp[j+1])/2)); 140 flag=0; 141 for(int k=0;k<n;k++) 142 { 143 if(lu.gfxj(le[k])) 144 { 145 flag=1; 146 break; 147 } 148 } 149 if(!flag) 150 { 151 rate+=cp[j+1]-cp[j]; 152 } 153 } 154 ans+=rate*le[i].len(); 155 } 156 printf("%.12f\n",ans); 157 } 158 return 0; 159 }
View Code

BNU校賽總決賽J 小白兔小灰兔 相交計算幾何模板