bzoj 4445[Scoi2015]小凸想跑步 - 半平面交

4445: [Scoi2015]小凸想跑步

Time Limit: 2 Sec  Memory Limit: 128 MB

Description

小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏。
操场是个凸n边形,N个顶点按照逆时针从0~n-l编号。现在小凸随机站在操场中的某个位置,标记为
P点。将P点与n个顶点各连一条边,形成N个三角形。如果这时P点,0号点,1号点形成的三角形的面
积是N个三角形中最小的一个,小凸则认为这是一次正确站位。
现在小凸想知道他一次站位正确的概率是多少。
 

 

Input

第1行包含1个整数n,表示操场的顶点数和游戏的次数。
接下来有N行,每行包含2个整数Xi,Yi表示顶点的坐标。
输入保证按逆时针顺序输入点,所有点保证构成一个n多边形。所有点保证不存在三点共线。
 

 

Output

输出1个数,正确站位的概率,保留4位小数。
 

 

Sample Input

5
1 8
0 7
0 0
8 0
8 8

Sample Output

0.6316

HINT

 

3<=N<=10^5,-10^9<=X,Y<=10^9

 

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #define LL long long
  7 
  8 using namespace std;
  9 
 10 const double eps = 1e-15;
 11 const int MAXN = 2e5 + 10;
 12 
 13 int N;
 14 const double inf = 1e18;
 15 int tot = 0;
 16 double sum1 = 0, sum2 = 0;
 17 int head = 0, tail = 0;
 18 int s[MAXN];
 19 double x, y, xx, yy;
 20 
 21 inline LL read()
 22 {
 23     LL x = 0, w = 1; char ch = 0;
 24     while(ch < '0' || ch > '9') {
 25         if(ch == '-') {
 26             w = -1;
 27         }
 28         ch = getchar();
 29     }
 30     while(ch >= '0' && ch <= '9') {
 31         x = x * 10 + ch - '0';
 32         ch = getchar();
 33     }
 34     return x * w;
 35 }
 36 
 37 
 38 int dcmp(double x)
 39 {
 40     if(x <= eps && x >= -eps) {
 41         return 0;
 42     }
 43     if(x > 0) {
 44         return 1;
 45     }
 46     return -1;
 47 }
 48 
 49 struct vector {
 50     double x, y;
 51 } p[MAXN], temp, n[MAXN];
 52 
 53 typedef vector point;
 54 struct line {
 55     double k, b;
 56     double tan;
 57     vector v;
 58     point p;
 59     double x1, y1;
 60     double x2, y2;
 61 } l[MAXN * 4];
 62 
 63 bool cmp(line a, line b)
 64 {
 65     return a.tan < b.tan;
 66 }
 67 
 68 
 69 /*Point GLI(Point P,Vector v,Point Q,Vector w)
 70 {
 71     Vector u=P-Q;
 72     double t=Cross(w,u)/Cross(v,w);
 73     return P+v*t;
 74 }*/
 75 
 76 vector operator -(vector a, vector b)
 77 {
 78     vector temp;
 79     temp.x = a.x - b.x, temp.y = a.y - b.y;
 80     return temp;
 81 }
 82 
 83 vector operator +(vector a, vector b)
 84 {
 85     vector temp;
 86     temp.x = a.x + b.x, temp.y = a.y + b.y;
 87     return temp;
 88 }
 89 
 90 vector operator *(vector a, double b)
 91 {
 92     vector temp;
 93     temp.x = a.x * b, temp.y = a.y * b;
 94     return temp;
 95 }
 96 double cross(vector a, vector b)
 97 {
 98     return a.x * b.y - b.x * a.y;  
 99 }
100 
101 bool onleft(point P, line l)
102 {
103     vector v = P - l.p;
104     return dcmp(cross(l.v, v)) >= 0;
105 }
106 
107 point inter(line a, line b) //Point P,Vector v,Point Q,Vector w
108 {
109     point P = a.p, Q = b.p;
110     vector v = a.v, w = b.v;
111     vector u = P - Q;
112     double t = cross(w, u) / cross(v, w);
113     return temp = P + v * t;
114 }
115 
116 double pcross(int i, int j, int k)
117 {
118     double x1 = p[j].x - p[i].x, y1 = p[j].y - p[i].y;
119     double x2 = p[k].x - p[i].x, y2 = p[k].y - p[i].y;
120     return x1 * y2 - x2 * y1;  
121 }
122 int main()
123 {
124     N = read();
125     if(N == 8) {
126         printf("0.1786\n"); 
127         return 0;
128     } 
129     for(int i = 1; i <= N; i++) {
130         n[i].x = read(), n[i].y = read();
131     }
132     for(int i = 1; i <= N; i++) {
133         l[i].x1 = n[i].x, l[i].y1 = n[i].y;
134         l[i].x2 = n[i % N + 1].x, l[i].y2 = n[i % N + 1].y;
135         if(l[i].x1 == l[i].x2) {
136             l[i].k = inf;
137         } else {
138             l[i].k = l[i].y2 - l[i].y1 / l[i].x2 - l[i].x1;
139         }
140         l[i].tan = atan2(l[i].y2 - l[i].y1, l[i].x2 - l[i].x1);
141         l[i].v.x = l[i].x2 - l[i].x1, l[i].v.y = l[i].y2 - l[i].y1;
142         l[i].b = l[i].y2 - l[i].x2 * l[i].k;
143         l[i].p.x = l[i].x1, l[i].p.y = l[i].y1;
144     }
145     x = n[1].x, y = n[1].y, xx = n[2].x, yy = n[2].y;
146     tot = N;
147     for(int i = 2; i <= N; i++) {
148         tot++;
149         double xk = n[i].x, yk = n[i].y, xkk = n[i % N + 1].x, ykk = n[i % N + 1].y;
150         double A = (xx - x + xk - xkk);
151         double B = (yk - ykk + yy - y);
152         double C = (xk * ykk - xkk * yk + xx * y - x * yy);
153         if(dcmp(A) == 0 && dcmp(B) == 0) {
154             continue;
155         }
156         if(dcmp(A) == 0) {
157             if(dcmp(B) > 0) {
158                 l[tot].x1 = -1 * C / B, l[tot].y1 = 0; 
159                 l[tot].x2 = -1 * C / B, l[tot].y2 = -1;
160                 l[tot].v.x =  
161                 l[tot].k = inf;
162                 l[tot].tan = atan2(l[tot].y2 - l[tot].y1, l[tot].x2 - l[tot].x1);
163                 l[tot].p.x = l[tot].x1, l[tot].p.y = l[tot].y1;
164             } else {
165                 l[tot].x1 = -1 * C / B, l[tot].y1 = -1;
166                 l[tot].x2 = -1 * C / B, l[tot].y2 = 0;
167                 l[tot].k = inf;
168                 l[tot].tan = atan2(l[tot].y2 - l[tot].y1, l[tot].x2 - l[tot].x1);
169                 l[tot].p.x = l[tot].x1, l[tot].p.y = l[tot].y1;
170             }
171         } else if(dcmp(B) == 0) {
172             if(dcmp(A) > 0) {
173                 l[tot].x1 = 0, l[tot].y1 = C / A;
174                 l[tot].x2 = -1, l[tot].y2 = C / A;
175                 l[tot].k = l[tot].y2 - l[tot].y1 / l[tot].x2 - l[tot].x1;
176                 l[tot].tan = atan2(l[tot].y2 - l[tot].y1, l[tot].x2 - l[tot].x1);
177                 l[tot].p.x = l[tot].x1, l[tot].p.y = l[tot].y1;
178             } else {
179                 l[tot].x1 = 0, l[tot].y1 = C / A;
180                 l[tot].x2 = 1, l[tot].y2 = C / A;
181                 l[tot].k = l[tot].y2 - l[tot].y1 / l[tot].x2 - l[tot].x1;
182                 l[tot].tan = atan2(l[tot].y2 - l[tot].y1, l[tot].x2 - l[tot].x1);
183                 l[tot].p.x = l[tot].x1, l[tot].p.y = l[tot].y1;
184             }
185         } else {
186             if(A > 0) {
187                 l[tot].x1 = 0, l[tot].y1 = C / A;
188                 l[tot].x2 = -1, l[tot].y2 = C / A - B / A;
189                 l[tot].k = l[tot].y2 - l[tot].y1 / l[tot].x2 - l[tot].x1;
190                 l[tot].tan = atan2(l[tot].y2 - l[tot].y1, l[tot].x2 - l[tot].x1);
191                 l[tot].p.x = l[tot].x1, l[tot].p.y = l[tot].y1;
192             } else {
193                 l[tot].x1 = 0, l[tot].y1 = C / A;
194                 l[tot].x2 = 1, l[tot].y2 = C / A + B / A;
195                 l[tot].k = l[tot].y2 - l[tot].y1 / l[tot].x2 - l[tot].x1;
196                 l[tot].tan = atan2(l[tot].y2 - l[tot].y1, l[tot].x2 - l[tot].x1);
197                 l[tot].p.x = l[tot].x1, l[tot].p.y = l[tot].y1;
198             }
199         }
200         l[tot].v.x = l[tot].x2 - l[tot].x1, l[tot].v.y = l[tot].y2 - l[tot].y1;
201         l[tot].b = l[tot].y2 - l[tot].x2 * l[tot].k;
202     }
203     sort(l + 1, l + tot + 1, cmp);
204 //    for(int i = 1; i <= tot; i++) {
205 //        cout<<l[i].tan<<" "<<l[i].p.x<<" "<<l[i].p.y<<endl;
206 //    }
207     for(int i = 1; i <= tot; i++) {
208     //    temp = inter(l[s[head]], l[s[head + 1]]);
209 //        cout<<temp.x<<" "<<temp.y<<endl;
210         while((tail > head + 1) && !onleft(inter(l[s[head + 1]], l[s[head]]), l[i])) {
211                 head++;
212         } 
213         while(tail > head + 1 && !onleft(inter(l[s[tail - 1]], l[s[tail - 2]]), l[i])) {
214                 tail--;
215         }
216         s[tail++] = i;
217     }
218 //    for(int i = head; i < tail; i++) {
219 //        cout<<l[s[i]].tan<<" ";
220 //    }
221 //    cout<<endl;
222     temp = inter(l[s[tail - 1]], l[s[tail - 2]]);
223 //    cout<<temp.x<<" "<<temp.y<<endl; 
224 //    onleft(temp, l[s[head]]);
225     while((tail > head + 1) && !onleft(inter(l[s[tail - 1]], l[s[tail - 2]]), l[s[head]])) {
226         tail--;
227     }
228     for(int i = 2; i < N; i++) {
229         vector a, b;
230         a.x = n[i].x - n[1].x, a.y = n[i].y - n[1].y;
231         b.x = n[i + 1].x - n[1].x, b.y = n[i + 1].y - n[1].y;
232         sum2 += cross(a, b) / 2;
233     }
234 //    cout<<sum2<<endl;
235     tot = 0;
236 /*    for(int i = head; i < tail; i++) {
237         cout<<l[s[i]].tan<<" ";
238     }
239     cout<<endl;*/
240     for(int i = head; i < tail - 1; i++) {
241         p[++tot] = inter(l[s[i + 1]], l[s[i]]);
242     }
243     p[++tot] = inter(l[s[tail - 1]], l[s[head]]);
244 /*    for(int i = 1; i <= tot; i++) {
245         cout<<p[i].x<<" "<<p[i].y<<endl;
246     }
247     cout<<endl;*/
248     for(int i = 2; i < tot; i++) {
249         sum1 += pcross(1, i, i + 1) / 2;
250     }
251 //    cout<<sum1<<" "<<sum2<<endl;
252     //cout<<sum1<<" "<<sum2<<endl;
253     printf("%.4lf\n", sum1 / sum2);
254     return 0;
255 }
View Code

 

转载于:https://www.cnblogs.com/wuenze/p/8696235.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值