计算几何基础

记录点滴。

  1 /*
  2 2015.6    HT
  3 ACM Work_8
  4 
  5 */
  6 
  7 #include <iostream>
  8 #include <cstdio>
  9 using namespace std;
 10 
 11 /*
 12 线段判交--ACM
 13 
 14 1.快速排斥实验
 15 设以线段P1P2和线段Q1Q2为对角线的矩形为M,N;若M,N 不相交,则两个线段显然不相交;
 16 2.跨立实验
 17 如果两线段相交,则两线段必然相互跨立对方。若P1P2跨立Q1Q2,则矢量(P1-Q1)和(P2-Q1)位于矢量(Q2-Q1)的两侧,
 18 即(P1-Q1)×(Q2-Q1)*(P2-Q1)×(Q2-Q1)<0,上式可改写成(P1-Q1)×(Q2-Q1)*(Q2-Q1)×(P2-Q1)>0。
 19 当(P1-Q1)×(Q2-Q1)=0时,说明(P1-Q1)和(Q2-Q1)共线,但是因为已经通过快速排斥试验,所以P1一定在线段Q1Q2上;
 20 同理,(Q2-Q1)×(P2-Q1)=0说明P2一定在线段Q1Q2上。
 21 所以判断P1P2跨立Q1Q2的依据是:(P1-Q1)×(Q2-Q1)*(Q2-Q1)×(P2-Q1)>=0。
 22 
 23 */
 24 
 25 /*
 26 You can Solve a Geometry Problem too
 27 判断两条线段是否相交
 28 
 29 向量 p1*p2 = x1y2 – y1x2 = -p2*p1
 30 */
 31 //struct Line
 32 //{
 33 //    double x1, y1, x2, y2;
 34 //}lines[110];
 35 //
 36 //bool isCross(Line a, Line b)
 37 //{
 38 //    if (((a.x1 - b.x1)*(a.y2 - b.y1) - (a.x2 - b.x1)*(a.y1 - b.y1)) * ((a.x1 - b.x2)*(a.y2 - b.y2) 
 39 //        - (a.x2 - b.x2)*(a.y1 - b.y2))>0)
 40 //        return false;
 41 //    if (((b.x1 - a.x1)*(b.y2 - a.y1) - (b.x2 - a.x1)*(b.y1 - a.y1)) * ((b.x1 - a.x2)*(b.y2 - a.y2) 
 42 //        - (b.x2 - a.x2)*(b.y1 - a.y2))>0)
 43 //        return false;
 44 //    return true;
 45 //}
 46 //
 47 //int main()
 48 //{
 49 //    int n;
 50 //    while (cin >> n && n)
 51 //    {
 52 //        int i;
 53 //        for (i = 0; i < n; ++i)
 54 //        {
 55 //            cin >> lines[i].x1 >> lines[i].y1 >> lines[i].x2 >> lines[i].y2;
 56 //        }
 57 //        int j;
 58 //        int ans = 0;
 59 //        for (i = 0; i < n; ++i)
 60 //        {
 61 //            for (j = i + 1; j < n; ++j)
 62 //            {
 63 //                if (isCross(lines[i], lines[j]) == true)
 64 //                {
 65 //                    ans++;
 66 //                }
 67 //            }
 68 //        }
 69 //        cout << ans << endl;
 70 //    }
 71 //    return 0;
 72 //}
 73 
 74 
 75 
 76 /*
 77 改革春风吹满地
 78 
 79 求多边形面积
 80 s = 1/2 * (求和i=0~(n-1)) { Xi*Y(i+1) - X(i+1)*Yi }
 81 逆时针给出点坐标,值为正
 82 顺时针给出点坐标,值为负
 83 */
 84 //int main()
 85 //{
 86 //    int n;
 87 //    int a[100], b[100], i;
 88 //    double s;
 89 //    while (cin >> n && n)
 90 //    {
 91 //        s = 0;
 92 //        for (i = 0; i < n; i++)
 93 //            cin >> a[i] >> b[i];
 94 //        a[n] = a[0];
 95 //        b[n] = b[0];
 96 //        for (i = 0; i<n; i++)
 97 //            s += (a[i] * b[i + 1] - a[i + 1] * b[i]);
 98 //        printf_s("%.1lf\n", s / 2);
 99 //    }
100 //    return 0;
101 //}
102 
103 
104 
105 /*
106 Shape of HDU
107 
108 判断该多边形是凸多边形还是凹多边形
109 */
110 //struct point
111 //{
112 //    int x, y;
113 //};
114 //
115 ///*
116 //两个向量 a-> (p1.x-p0.x, p1.y-p0.y)  和 b->(p2.x-p1.x, p2.y-p1.y)
117 //两个向量叉积 (a.x*b.y - a.y*b.x)
118 //叉积结果 >0 ,则向量 a 在向量 b的顺时针方向; <0则相反; 等于0则在同一直线
119 //*/
120 //double cross(point p0, point p1, point p2)
121 //{
122 //    return (p1.x - p0.x)*(p2.y - p1.y) - (p1.y - p0.y)*(p2.x - p1.x);
123 //}
124 //
125 //int main()
126 //{
127 //    int n;
128 //    point p[1010];
129 //    while (scanf_s("%d", &n) && n)
130 //    {
131 //        int i, flag = 0;
132 //        for (i = 0; i<n; i++)
133 //        {  
134 //            scanf_s("%d%d", &p[i].x, &p[i].y);
135 //        }
136 //        p[n] = p[0];
137 //        p[n + 1] = p[1]; // 增加两个点代表最开始的两个点,以形成循环 
138 //        for (i = 2; i <= n + 1; i++)
139 //        {
140 //            if (cross(p[i - 2], p[i - 1], p[i])<0) 
141 //                flag = 1;
142 //        }
143 //        if (!flag)
144 //            printf_s("convex\n");
145 //        else 
146 //            printf_s("concave\n");
147 //    }
148 //    return 0;
149 //}
150 
151 
152 
153 /*
154 Surround the Trees
155 
156 */
157 #define MAXD 110
158 
159 typedef struct
160 {
161     double x, y;
162 }point;
163 point Tree[MAXD], Result[MAXD];
164 int N, P;
165 
166 /*
167 叉乘
168 P1 x P2
169 >0 : P1 is clockwise from P2 with respect to (0,0)
170 <0 : counterclockwise (即P1在P2左边)
171 =0 : collinear
172 */
173 double cross(double x1, double y1, double x2, double y2)
174 {
175     return x1 * y2 - x2 * y1;
176 }
177 
178 // 按 y坐标从低到高排序,若 y相等则按 x坐标排序
179 int cmp(const void *_p, const void *_q)
180 {
181     point *p = (point *)_p, *q = (point *)_q;
182     if (p->y == q->y)
183         return p->x < q->x ? -1 : 1;
184 
185     return p->y < q->y ? -1 : 1;
186 }
187 
188 double Distance(double x, double y, double x1, double y1)
189 {
190     double temp1 = (x - x1)*(x - x1);
191     double temp2 = (y - y1)*(y - y1);
192     return sqrt(temp1 + temp2);
193 }
194 
195 double sqr(double x)
196 {
197     return x * x;
198 }
199 
200 // 是否删除
201 int del(int top, int i)
202 {
203     if (cross(Result[top].x - Result[top - 1].x, Result[top].y - Result[top - 1].y,
204         Tree[i].x - Result[top].x, Tree[i].y - Result[top].y) < 0)
205         return 1;
206     return 0;
207 }
208 
209 int graham()
210 {
211     int i, mint, top = 1;
212     Result[0] = Tree[0];
213     Result[1] = Tree[1];
214     for (i = 2; i < N; i++)
215     {
216         while (top && del(top, i))
217             --top;
218         Result[++top] = Tree[i];
219     }
220     mint = top;
221     Result[++top] = Tree[N - 2];
222     for (i = N - 3; i >= 0; i--)
223     {
224         while (top != mint && del(top, i))
225             --top;
226         Result[++top] = Tree[i];
227     }
228     return top;
229 }
230 
231 int main()
232 {
233     int i;
234     double sum;
235     while (1)
236     {
237         cin >> N;
238         if (!N)
239             break;
240 
241         for (i = 0; i < N; i++)
242             cin >> Tree[i].x >> Tree[i].y;
243 
244         // 快排
245         qsort(Tree, N, sizeof(Tree[0]), cmp);
246         sum = 0;
247 
248         if (N == 1)
249             printf_s("0.00\n");
250         else if (N == 2)
251         {
252             sum = Distance(Tree[0].x, Tree[0].y, Tree[1].x, Tree[1].y);
253             printf_s("%.2f\n", sum);
254         }
255         else
256         {
257             P = graham();
258             for (i = 0; i < P; i++)
259                 sum += Distance(Result[i].x, Result[i].y, Result[i + 1].x, Result[i + 1].y);
260             printf_s("%.2f\n",sum);
261         }
262     }
263     return 0;
264 }

 

posted @ 2015-06-12 23:27  ht-beyond  阅读(218)  评论(0编辑  收藏  举报