博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/38827629
多校第十场的一道几何,做了好久了,忘了发出来。比赛的时候由于坑爹的模板,后台100组数据错了一组,导致比赛的时候没做出来,赛后郁闷了好久。。。。。比赛之后好好整了一下凸包的模板,代码里会是Graham算法,标程用的是Andrew算法。
题目大意:一个无限大的平面上,有间距为D的无限条水平直线,如图所示。
给你一个直径为D的硬币,硬币中有n个点,每两个点之间都有一条线段,任意三点不会共线。随机的将硬币扔到上图中的平面内,问至少有一条线段跟平面内的直线相交的概率是多少。
解题思路:很容易想到的是,对于硬币上的所有点来说,无疑是构成一个凸包的时候为所求的情况,而当点的个数为1的时候,概率为0。
1 #include <stdio.h> 2 #include <math.h> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const double eps = 1e-6; 7 const double Pi = acos(-1.0); 8 #define zero(x) (((x) > 0 ? (x) : (-x)) < eps) 9 10 int q, n; 11 12 struct Point 13 { 14 double x,y; 15 Point() {} Point(double _x,double _y) 16 { 17 x = _x; 18 y = _y; 19 } Point operator -(const Point &b)const 20 { 21 return Point(x - b.x,y - b.y); 22 } //叉积 23 double operator ^(const Point &b)const 24 { 25 return x*b.y - y*b.x; //点积 26 } 27 double operator *(const Point &b)const 28 { 29 return x*b.x + y*b.y; //绕原点旋转角度B(弧度值),后x,y的变化 30 } 31 void transXY(double B) 32 { 33 double tx = x,ty = y; 34 x = tx*cos(B) - ty*sin(B); 35 y = tx*sin(B) + ty*cos(B); 36 } 37 } P[105], ch[105]; 38 39 double Distance(Point a, Point b){ 40 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 41 } 42 double xmult(Point p1, Point p2, Point p){ 43 return (p1.x-p.x)*(p2.y-p.y) - (p1.y-p.y)*(p2.x-p.x); 44 } 45 int dcmp(double x){ 46 return fabs(x)<eps?0:(x<0?-1:1); 47 } 48 bool cmp(Point a, Point b){ 49 if(dcmp(xmult(a, b, P[0])) == 0){ 50 return Distance(a, P[0]) < Distance(b, P[0]); 51 } 52 else { 53 return dcmp(xmult(a, b, P[0])) > 0; 54 } 55 } 56 int Graham(int n){ 57 int s = 0, top = 1; 58 for(int i = 0; i < n; ++i){ 59 if(P[i].y < P[s].y || (P[i].y == P[s].y && P[i].x < P[s].x)){ 60 s = i; 61 } 62 } 63 if(s != 0){ 64 Point tmp = P[0]; 65 P[0] = P[s]; 66 P[s] = tmp; 67 } 68 sort(P+1, P+n, cmp); 69 ch[0] = P[0], ch[1] = P[1]; 70 for(int i = 2; i < n; ++i){ 71 while(top > 0 && dcmp(xmult(ch[top], P[i], ch[top-1])) < 0){ 72 top--; 73 } 74 ch[++top] = P[i]; 75 } 76 return top+1; 77 } 78 79 80 int T; 81 double d; 82 83 int main() 84 { 85 //freopen("1008.in", "r", stdin); 86 //freopen("data.out", "w", stdout); 87 int icase = 1; 88 scanf("%d", &T); 89 while(T--){ 90 scanf("%d%lf", &n, &d); 91 for(int i = 0; i < n; ++i){ 92 scanf("%lf%lf", &P[i].x, &P[i].y); 93 } 94 printf("Case #%d: ", icase++); 95 if(n >= 3){ 96 int t = Graham(n); 97 //printf("%d ", t); 98 double sum = Distance(ch[0], ch[t-1]); 99 for(int i = 0; i < t-1; ++i){ 100 sum += Distance(ch[i], ch[i+1]); 101 } 102 //printf("q = %d ", q); 103 //printf("%lf ", Area()); 104 //printf("%lf " ,sum); 105 printf("%.4lf ", sum/(Pi*(d))); 106 } 107 else if(n == 2){ 108 double dis = Distance(P[0], P[1]); 109 printf("%.4lf ", 2*dis/(Pi*d)); 110 } 111 else { 112 printf("0.0000 "); 113 } 114 //printf("%lf %lf ", Min.y, Max.y); 115 } 116 117 return 0; 118 } 119 120 /* 121 100 122 3 3 123 0 1 124 1 0 125 -1 0 126 */