ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

587. 安装栅栏(凸包问题)

2022-04-27 02:00:50  阅读:190  来源: 互联网

标签:587 栅栏 const top trees st vector return 凸包


587. 安装栅栏

在一个二维的花园中,有一些用 (x, y) 坐标表示的树。由于安装费用十分昂贵,你的任务是先用最短的绳子围起所有的树。只有当所有的树都被绳子包围时,花园才能围好栅栏。你需要找到正好位于栅栏边界上的树的坐标。

 

示例 1:

输入: [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]]
输出: [[1,1],[2,0],[4,2],[3,3],[2,4]]
解释:

 

 


示例 2:

输入: [[1,2],[2,2],[4,2]]
输出: [[1,2],[2,2],[4,2]]
解释:

 

 


即使树都在一条直线上,你也需要先用绳子包围它们。

 

注意:

  1. 所有的树应当被围在一起。你不能剪断绳子来包围树或者把树分成一组以上。
  2. 输入的整数在 0 到 100 之间。
  3. 花园至少有一棵树。
  4. 所有树的坐标都是不同的。
  5. 输入的点没有顺序。输出顺序也没有要求。
 1 vector<int> start; // 凸包起点坐标
 2 // 排序找第一个点,先按y轴升序,如果y轴相等,则按x轴升序
 3 inline bool cmp1(const vector<int> &a, const vector<int> &b) {
 4     // y轴相等,则按照x轴升序排序
 5     if (a[1] == b[1]) {
 6         return a[0] < b[0];
 7     } else {
 8         return a[1] < b[1];
 9     }
10 }
11 // 两条边(向量)的叉积, 向量ab与向量ac的叉积
12 inline  double cross(const vector<int> &a, const vector<int> &b, const vector<int> &c) { // 计算叉积
13     return ((b[0] - a[0]) * (c[1] - a[1]) * 1.0 - (b[1] - a[1]) * (c[0] - a[0]));
14 }
15 // 计算线段ab的长度
16 inline  double distance(const vector<int> & a, const vector<int> & b) {
17     return (a[0] - b[0]) * (a[0] - b[0]) * 1.0 + (a[1] - b[1]) * (a[1] - b[1]);
18 }
19 // 按照夹角从小到大排序,夹角相同时按照x轴升序排序
20 inline bool cmp2(const vector<int> &a, const vector<int> &b) {
21     int diff = cross(start, a, b);
22     if (diff == 0) {
23         return distance(start, a) < distance(start, b);
24     } else {
25         return diff > 0;
26     }
27 }
28 class Solution {
29 public:
30     vector<vector<int>> outerTrees(vector<vector<int>> &trees) {
31         int n = trees.size();
32         if (n < 4) {
33             return trees;
34         }
35         // 对trees按y轴升序排序
36         sort(trees.begin(), trees.end(), cmp1);
37         start = trees[0];
38         /* 除凸包起点外剩余点按照极坐标的角度大小进行排序 */
39         sort(trees.begin() + 1, trees.end(), cmp2);
40         /* 对于凸包最后且在同一条直线的元素按照距离从大到小进行排序 */
41         int r = n - 1;
42         while (r >= 0 && cross(trees[0], trees[n - 1], trees[r]) == 0) {
43             r--;
44         }
45         for (int l = r + 1, h = n - 1; l < h; l++, h--) {
46             swap(trees[l], trees[h]);
47         }
48         stack<int> st; // 存储点在trees中的下标索引
49         st.emplace(0);
50         st.emplace(1);
51         for (int i = 2; i < n; i++) {
52             int top = st.top();
53             st.pop();
54             /* 如果当前元素与栈顶的两个元素构成的向量顺时针旋转,则弹出栈顶元素 */
55             while (!st.empty() && cross(trees[st.top()], trees[top], trees[i]) < 0) {
56                 top = st.top();
57                 st.pop();
58             }
59             st.emplace(top);
60             st.emplace(i);
61         }
62 
63         vector<vector<int>> res;
64         while (!st.empty()) {
65             res.emplace_back(trees[st.top()]);
66             st.pop();
67         }
68         return res;
69     }
70 };

标签:587,栅栏,const,top,trees,st,vector,return,凸包
来源: https://www.cnblogs.com/MGFangel/p/16197390.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有