Find the Border
题意: 给n个点连成的多边形,求边界.
从左下角的点开始走,每次走需要右转最多的点. 类似卷包裹.
1 /************************************************************************* 2 > File Name: board.cpp 3 > Author: yijiull 4 > Mail: 1147161372@qq.com 5 > Created Time: 2017年09月23日 星期六 10时50分19秒 6 ************************************************************************/ 7 #include <iostream> 8 #include <cstring> 9 #include <cstdio> 10 #include <bits/stdc++.h> 11 using namespace std; 12 #define FP freopen("in.txt", "r", stdin) 13 const double eps = 1e-9; 14 const double pi = acos(-1.0); 15 const int inf = 0x3f3f3f3f; 16 struct Point { 17 double x,y; 18 Point (double x = 0, double y = 0) : x(x), y(y) {} 19 }; 20 typedef Point Vector; 21 Vector operator + (Vector a, Vector b) { 22 return Vector (a.x + b.x, a.y + b.y); 23 } 24 Vector operator * (Vector a, double s) { 25 return Vector (a.x * s, a.y * s); 26 } 27 Vector operator / (Vector a, double p) { 28 return Vector (a.x / p, a.y / p); 29 } 30 Vector operator - (Point a, Point b) { 31 return Vector (a.x - b.x, a.y - b.y); 32 } 33 bool operator < (Point a, Point b) { 34 return a.x < b.x || (a.x == b.x && a.y < b.y); 35 } 36 int dcmp (double x) { 37 if(fabs(x) < eps) return 0; 38 return x < 0 ? -1 : 1; 39 } 40 bool operator == (const Point &a, const Point &b) { 41 return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0; 42 } 43 double Dot(Vector a, Vector b) { 44 return a.x * b.x + a.y * b.y; 45 } 46 double Length (Vector a) { 47 return sqrt(Dot(a, a)); 48 } 49 double Angle (Vector a) { 50 return atan2(a.y, a.x); 51 } 52 double Cross (Vector a, Vector b) { 53 return a.x * b.y - a.y * b.x; 54 } 55 //两直线交点 56 Point GetLineIntersection (Point p, Vector v, Point q, Vector w) { 57 Vector u = p - q; 58 double t1 = Cross(w, u) / Cross(v, w); 59 double t2 = Cross(v, u) / Cross(v, w); 60 return p + v * t1; // return q + w * t2; 61 } 62 //判断两线段是否规范相交 63 bool SegmentProperIntersection(Point a1, Point b1, Point a2, Point b2) { 64 double c1 = Cross(b1 - a1, a2 - a1), c2 = Cross(b1 - a1, b2 - a1), 65 c3 = Cross(b2 - a2, a1 - a2), c4 = Cross(b2 - a2, b1 - a2); 66 return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0; 67 } 68 //判断点是否在线段上(即∠PAB等于π) 69 bool OnSegment(Point p, Point a, Point b) { 70 return dcmp(Cross(a - p, b - p)) == 0 && dcmp(Dot(a - p, b - p)) < 0; 71 } 72 const int maxn = 1010; 73 Point p[maxn], res[maxn], temp[maxn]; 74 double ang[maxn], s; 75 int cnt; 76 void add(Point a, Point b) { 77 temp[cnt] = a; 78 ang[cnt] = atan2(a.y - b.y, a.x - b.x) - s; 79 while(dcmp(ang[cnt]) <= 0) ang[cnt] += 2*pi; 80 cnt++; 81 } 82 int main(){ 83 int n; 84 //FP; 85 while(scanf("%d", &n) != EOF) { 86 int fg = 0; 87 for(int i = 0; i < n; i++) { 88 scanf("%lf%lf", &p[i].x, &p[i].y); 89 if(p[i] < p[fg]) fg = i; 90 } 91 res[0] = p[fg]; 92 int num = 1; 93 s = -pi; 94 while (1) { 95 cnt = 0; 96 for (int i = 0; i < n; i++) { 97 if (res[num - 1] == p[i]) { 98 add(p[(i + 1) % n], res[num - 1]); 99 add(p[(i + n - 1) % n], res[num - 1]); 100 break; 101 } 102 } 103 for (int i = 0; i < n; i++) { 104 if (OnSegment(res[num - 1], p[i], p[(i + 1) % n])) { 105 add(p[(i + 1) % n], res[num - 1]); 106 add(p[i], res[num - 1]); 107 } 108 } 109 int id = 0; 110 for (int i = 0; i < cnt; i++) 111 if (ang[i] < ang[id]) 112 id = i; 113 double minlen = 1e9; 114 Point RP = temp[id], its; 115 for (int i = 0; i < n; i++) { 116 if (SegmentProperIntersection(temp[id], res[num - 1], p[i], p[(i + 1) % n])) { 117 its = GetLineIntersection(temp[id], temp[id] - res[num - 1], p[i], p[i] - p[(i + 1) % n]); 118 if (Length(its - res[num - 1]) < minlen) { 119 minlen = Length(its - res[num - 1]); 120 RP = its; 121 } 122 } 123 } 124 res[num] = RP; 125 s = atan2(res[num - 1].y - res[num].y, res[num - 1].x - res[num].x); 126 num++; 127 if (res[num - 1] == res[0]) 128 break; 129 } 130 printf("%d ", num - 1); 131 for(int i = 0; i< num-1; i++) 132 printf("%.4lf %.4lf ",res[i].x,res[i].y); 133 } 134 return 0; 135 }