Find the Border UVALive - 3218 (卷包裹)

Posted yijiull

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Find the Border UVALive - 3218 (卷包裹)相关的知识,希望对你有一定的参考价值。

Find the Border

 UVALive - 3218 

题意: 给n个点连成的多边形,求边界.

从左下角的点开始走,每次走需要右转最多的点. 类似卷包裹.

技术分享
  1 /*************************************************************************
  2     > File Name: board.cpp
  3     > Author: yijiull
  4     > Mail: [email protected] 
  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\n", num - 1);
131         for(int i = 0; i< num-1; i++) 
132             printf("%.4lf %.4lf\n",res[i].x,res[i].y);
133     }
134     return 0;
135 }
View Code

 

以上是关于Find the Border UVALive - 3218 (卷包裹)的主要内容,如果未能解决你的问题,请参考以下文章

UVALive - 6185 Find the Outlier暴力填表+高斯消元+卡eps

LA3218 Find the Border

UVALive - 3942 Remember the Word[树状数组]

UVALive - 3942 Remember the Word[Trie DP]

UVALive7146 Defeat the Enemy

UVALive 3942 Remember the Word