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 }

时间: 2024-08-03 01:29:34

Find the Border UVALive - 3218 (卷包裹)的相关文章

uva 1340 - Find the Border(卷包裹)

题目链接:uva 1340 - Find the Border 模仿别人代码写的卷包裹算法.就是沿着折线的外围走一圈,每次到一个新的点需要转弯时转向向右拐最多的那条. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <complex> #include <algorithm> using namespace std; ty

uvalive 3218 Find the Border

题意:一条封闭折线将平面分成了若干个区域,按顺序给出折线各点的坐标,要求输出封闭折线的轮廓. 题解:用类似卷包裹的算法,先确定一个一定会被选中的点(x坐标最小,y坐标最小)作为起点,然后把可能是下一个极点(凸包顶点)的点都存起来,下一个极点有可能是当前点所在线段的前一个点和后一个点或当前点所在线段和其他线段的有交点的线段的起点和终点. 找出最右侧的点(用角度判断)和当前点的连线是否和其他线段有交点,如果有就找最近的交点当做答案的下一个点,如果没有最右侧的点就是下一个点.最后转回起点结束. 1 #

POJ 1696 Space Ant 卷包裹法

Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3316   Accepted: 2118 Description The most exciting space discovery occurred at the end of the 20th century. In 1999, scientists traced down an ant-like creature in the planet Y19

uvalive 3218

题意:一条封闭折线将平面分成了若干个区域,按顺序给出折线各点的坐标,要求输出封闭折线的轮廓. 题解:用类似卷包裹的算法,先确定一个一定会被选中的点(x坐标最小,y坐标最小)作为起点,然后把可能是下一个极点(凸包顶点)的点都存起来,下一个极点有可能是当前点所在线段的前一个点和后一个点或当前点所在线段和其他线段的有交点的线段的起点和终点. 找出最右侧的点(用角度判断)和当前点的连线是否和其他线段有交点,如果有就找最近的交点当做答案的下一个点,如果没有最右侧的点就是下一个点.最后转回起点结束. #in

POJ 1113 Wall 卷包裹法求凸包

Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 31199   Accepted: 10521 Description Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's castle. The King was so greedy, that he w

[POJ1113&amp;POJ1696]凸包卷包裹算法和Graham扫描法应用各一例

凸包的算法比较形象好理解 代码写起来也比较短 所以考前看一遍应该就没什么问题了..>_< POJ1113 刚开始并没有理解为什么要用凸包,心想如果贴着城堡走不是更好吗? 突然发现题目中有要求在满足把所有点包括在内的情况下周长最短...这不就是凸包的性质吗? 而且显然如果城堡是凹的话,往里面绕一圈肯定会使周长增加... 然后可以从简单的三角形四边形推广出去,发现每个拐角-左右各90度之后所有的加和为180度 也就是在城堡周长的基础上再加一个半径为L的圆周长即是所求答案. 上次的模板写错了...应

Poj 3525 Most Distant Point from the Sea

地址:http://poj.org/problem?id=3525 题目: Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5167   Accepted: 2331   Special Judge Description The main land of Japan called Honshu is an island surrounded by the s

(转载)ACM训练计划,先过一遍基础再按此拼搏吧!!!!

ACM大量习题题库 ACM大量习题题库 现在网上有许多题库,大多是可以在线评测,所以叫做Online Judge.除了USACO是为IOI准备外,其余几乎全部是大学的ACM竞赛题库. USACO http://ace.delos.com/usacogate 美国著名在线题库,专门为信息学竞赛选手准备 TJU http://acm.tongji.edu.cn/ 同济大学在线题库,唯一的中文题库,适合NOIP选手 ZJU http://acm.zju.edu.cn/ 浙江大学在线题库 JLU htt

POJ 1696

这题是明显的TU包变形. 使用卷包裹法可解,而且是必定可以经过所有点的.直观可知,当经过某点后,相当于把之前的点抹去,求剩下点的TU包,递归下去,也就能把点全部经过了. 于是,只需把经过的点标记一下就可以了. #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <cmath> using namespace std; const