【kuangbin专题】计算几何基础(多边形)

【HDU 1115】

【题目大意】求多边形的重心

【解题分析】直接推公式,cx=∑x*面积 / 总面积 ,cy对称

 

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 using namespace std;
 5 const double eps  = 1e-9;
 6 const int    MAXN = 1e6 +5;
 7 int sgn(double x)
 8 {
 9     if (x < -eps)    return -1;
10     if (x > eps)    return 1;
11     return 0;
12 }
13 struct V
14 {
15     double x, y;
16     double ang;
17     double angle()
18     {//求取极
19         return atan2(y,x);
20     }
21     V(double X = 0, double Y = 0)
22     {
23         //初始化
24         x = X, y = Y;
25         ang = atan2(y, x);
26     }
27     bool operator <(const V &b)
28     {
29         return ang<b.ang;
30     }
31     bool operator ==(const V &b)
32     {
33         return sgn(x - b.x) && sgn(y - b.y);
34     }
35 
36 };
37 typedef V  P;
38 V operator +(V a, V b) { return V(a.x + b.x, a.y + b.y); }
39 V operator -(V a, V b) { return V(a.x - b.x, a.y - b.y); }
40 V operator *(V a, double b) { return V(a.x *b, a.y*b); }
41 V operator /(V a, double b) { return V(a.x / b, a.y / b); }
42 //叉积
43 double cross(V a, V b)
44 {
45     return a.x*b.y - a.y*b.x;
46 }
47 double cross(V a, V b, V c)
48 {
49     return cross(a - c, b - c);
50 }
51 //点积
52 double dot(V a, V b)
53 {
54     return a.x*b.x + a.y*b.y;
55 }
56 double area(P *p, int n)
57 {
58     double res = 0;
59     p[n + 1] = p[1];
60     for (int i = 1; i <= n; i++)
61         res += cross(p[i], p[i + 1]);
62     return res / 2;
63 }
64 P p[MAXN];
65 int main()
66 {
67     int T;
68     scanf("%d", &T);
69     while (T--)
70     {
71         int N, n = 0;
72         scanf("%d", &N);
73         for (int i = 1; i <= N; i++)
74         {
75             ++n;
76             scanf("%lf %lf", &p[n].x, &p[n].y);
77         }
78         double low = 0;
79         double ansx = 0, ansy = 0;
80         P a[5];
81         a[1] = p[1], a[2] = p[2];
82         for (int i = 3; i <= n; i++)
83         {
84             a[3] = p[i];
85             double s = area(a, 3);
86             low += s;
87             double tx = (a[1].x + a[2].x + a[3].x) ,
88                    ty = (a[1].y + a[2].y + a[3].y) ;
89             ansx += tx * s;
90             ansy += ty * s;
91             a[2] = a[3];
92         }
93         ansx =  ansx /low/3;
94         ansy =  ansy /low/3;
95         printf("%.2f %.2f\n", ansx,ansy);
96     }
97     return 0;
98 }
View Code

 

 

 


 【UVALive 3263】That Nice Euler Circuit

【题目大意】给定几个点,给出顺序为他们被一笔画的顺序,最后结尾在最开始的点形成一个闭合的图形,问这个一笔画把这个平面分成了几个部分

【题目分析】

因为有交点,有边线,这个问题可以转化成,求一个多边形有多少个面

开始这里想不通为什么要这么求,用空间思想想一下,按照每条边并在一起这样分的话是不是就能够形成一个多面体

而有欧拉定理,E为点数,V为边数,F为面数,有公式:F + V - E = 2

所以我们最后所求的面数即为:F = (  E  +  2  -  V )

然后我们计算有多少条边和点,就能够得到答案

对于点的情况:需要排除掉几根线交于一点的情况

对于边的情况:线上没多出一点就会被分割出来一条边

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 using namespace std;
  6 const int    MAXN = 90005;
  7 const double eps = 1e-9;
  8 int sgn(double x)
  9 {
 10     if (x < -eps)    return -1;
 11     if (x > eps)    return 1;
 12     return 0;
 13 }
 14 struct V
 15 {
 16     double x, y;
 17     double ang;
 18     double angle()
 19     {//求取极角
 20         return atan2(y, x);
 21     }
 22     V(double X = 0, double Y = 0)
 23     {
 24         //初始化
 25         x = X, y = Y;
 26         ang = atan2(y, x);
 27     }
 28     bool operator ==(const V &b)
 29     {
 30         return sgn(x - b.x)==0 && sgn(y - b.y)==0;
 31     }
 32     bool operator<(V a)
 33     {
 34         return x < a.x || (x == a.x && y < a.y);
 35     }
 36 };
 37 typedef V P;
 38 V operator +(V a, V b) { return V(a.x + b.x, a.y + b.y); }
 39 V operator -(V a, V b) { return V(a.x - b.x, a.y - b.y); }
 40 double operator *(V a, V b) { return a.x*b.x + a.y*b.y; }
 41 double operator ^(V a, V b) { return a.x*b.y - b.x*a.y; }
 42 V operator *(V a, double b) { return V(a.x *b, a.y*b); }
 43 V operator /(V a, double b) { return V(a.x / b, a.y / b); }
 44 //叉积
 45 double cross(P a, P b ,P c)
 46 {
 47     return (a - c) ^ (b - c);
 48 }
 49 struct L
 50 {
 51     P s, t;
 52     double ang;
 53     L(P X = V(), P Y = V())
 54     {
 55         s = X, t = Y, ang = (Y - X).angle();
 56     }
 57 };
 58 P p[MAXN],v[MAXN];
 59 L l[MAXN];
 60 //求两线段是否相交
 61 bool L_is_inter(L a, L b)
 62 {
 63     return
 64         max(a.s.x, a.t.x) >= min(b.s.x, b.t.x) &&
 65         max(b.s.x, b.t.x) >= min(a.s.x, a.t.x) &&
 66         max(a.s.y, a.t.y) >= min(b.s.y, b.t.y) &&
 67         max(b.s.y, b.t.y) >= min(a.s.y, a.t.y) &&
 68         sgn((b.s - a.s) ^ (a.t - a.s))*sgn((b.t - a.s) ^ (a.t - a.s)) < 0 &&
 69         sgn((a.s - b.s) ^ (b.t - a.s))*sgn((a.t - b.s) ^ (b.t - b.s)) < 0;
 70 }
 71 P intersection(L a, L b)
 72 {
 73     return a.s + (a.t - a.s)*(((b.t - b.s)^(a.s - b.s)) / ((a.t - a.s)^( b.t - b.s)));
 74 }
 75 bool P_is_onL(P a, P b,P c)
 76 {
 77     
 78     return sgn((b-a)^(c-a)) == 0 && sgn((b-a)*(c-a)) < 0;
 79 }
 80 int main()
 81 {
 82 
 83     int n; int cas = 0;
 84     while (scanf("%d", &n))
 85     {
 86         if (n == 0) break;
 87         int m = 0, c = 0;
 88         for (int i = 1; i <= n; i++)
 89         scanf("%lf %lf", &p[i].x, &p[i].y), v[i] = p[i];
 90         n--;
 91         for (int i = 1; i <= n; i++)
 92         {
 93             l[++m] = L(p[i], p[i + 1]);
 94         }
 95         c = n;
 96         for (int i = 1; i <= n; i++)
 97         {
 98             for (int j = i+1; j <= n; j++)
 99             {
100                 if (L_is_inter(l[i], l[j]))
101                 {
102                     v[++c] = intersection(l[i], l[j]);
103                 }
104             }
105         }
106         int e = m;
107         sort(v + 1, v + 1 + c);
108         c = unique(v + 1, v + 1 + c) - (v);
109         c--;
110         for (int i = 1; i <= c; i++)
111         {
112             for (int j = 1; j <= n; j++)
113             {
114                 if (P_is_onL(v[i],p[j], p[j+1]))
115                     e++;
116             }
117         }
118         printf("Case %d: There are %d pieces.\n",++cas,e + 2 - c);
119     }
120     return 0;
121 }
View Code

 

posted @ 2019-10-25 15:19  rentu  阅读(306)  评论(0编辑  收藏  举报