博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 1392 Surround the Trees(凸包)题解
阅读量:4322 次
发布时间:2019-06-06

本文共 2745 字,大约阅读时间需要 9 分钟。

题意:给一堆二维的点,问你最少用多少距离能把这些点都围起来

思路:

凸包:

我们先找到所有点中最左下角的点p1,这个点绝对在凸包上。接下来对剩余点按照相对p1的角度升序排序,角度一样按距离升序排序。因为凸包有一个特点,从最左下逆时针走,所有线都在当前这条向量的左边,根据这个特点我们进行判断。我们从栈顶拿出两个点s[top-1],s[top],所以如果s[top-1] -> p[i] 在 s[top-1] -> s[top] 右边,那么s[top]就不是凸包上一点,就这样一直判断下去。判断左右可以用叉乘。

参考:

模板(考虑n <= 2):

struct node{    double x, y;}p[maxn], s[maxn];int n, top;double dis(node a, node b){    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}bool cmp(node a, node b){    double A = atan2((a.y - p[1].y), (a.x - p[1].x));    double B = atan2((b.y - p[1].y), (b.x - p[1].x));    if(A != B) return A < B;    else{        return dis(a, p[1]) < dis(b, p[1]);    }}double cross(node a, node b, node c){   //(a->b)X(a->c)    return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);}void solve(){    int pos = 1;    for(int i = 2; i <= n; i++){        if(p[i].y < p[pos].y || (p[i].y == p[pos].y && p[i].x < p[pos].x)){            pos = i;        }    }    swap(p[1], p[pos]);    sort(p + 2, p + n + 1, cmp);    s[0] = p[1], s[1] = p[2];    top = 1;    for(int i = 3; i <= n; i++){        while(top >= 1 && cross(s[top - 1], p[i], s[top]) >= 0){ //向右转出栈            top--;        }        s[++top] = p[i];    }}

 

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef long long ll;using namespace std;const int maxn = 150 + 10;const int MOD = 1e9 + 7;const int INF = 0x3f3f3f3f;struct node{ double x, y;}p[maxn], s[maxn];int n, top;double dis(node a, node b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}bool cmp(node a, node b){ double A = atan2((a.y - p[1].y), (a.x - p[1].x)); double B = atan2((b.y - p[1].y), (b.x - p[1].x)); if(A != B) return A < B; else{ return dis(a, p[1]) < dis(b, p[1]); }}double cross(node a, node b, node c){ //(a->b)X(a->c) return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);}void solve(){ int pos = 1; for(int i = 2; i <= n; i++){ if(p[i].y < p[pos].y || (p[i].y == p[pos].y && p[i].x < p[pos].x)){ pos = i; } } swap(p[1], p[pos]); sort(p + 2, p + n + 1, cmp); s[0] = p[1], s[1] = p[2]; top = 1; for(int i = 3; i <= n; i++){ while(top >= 1 && cross(s[top - 1], p[i], s[top]) >= 0){ //向左转出栈 top--; } s[++top] = p[i]; }}int main(){ while(~scanf("%d", &n) && n){ for(int i = 1; i <= n; i++){ scanf("%lf%lf", &p[i].x, &p[i].y); } if(n == 1){ printf("0.00\n"); continue; } if(n == 2){ printf("%.2lf\n", dis(p[1], p[2])); continue; } solve(); double ans = 0; for(int i = 0; i < top; i++){ ans += dis(s[i], s[i + 1]); } ans += dis(s[top], s[0]); printf("%.2lf\n", ans); } return 0;}

 

转载于:https://www.cnblogs.com/KirinSB/p/10414378.html

你可能感兴趣的文章
HNOI2016
查看>>
JVM介绍
查看>>
将PHP数组输出为HTML表格
查看>>
Java中的线程Thread方法之---suspend()和resume() 分类: ...
查看>>
经典排序算法回顾:选择排序,快速排序
查看>>
BZOJ2213 [Poi2011]Difference 【乱搞】
查看>>
c# 对加密的MP4文件进行解密
查看>>
AOP面向切面编程C#实例
查看>>
Win form碎知识点
查看>>
避免使用不必要的浮动
查看>>
第一节:ASP.NET开发环境配置
查看>>
sqlserver database常用命令
查看>>
rsync远程同步的基本配置与使用
查看>>
第二天作业
查看>>
访问属性和访问实例变量的区别
查看>>
Spring MVC 异常处理 - SimpleMappingExceptionResolver
查看>>
props 父组件给子组件传递参数
查看>>
【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
查看>>
十二种获取Spring的上下文环境ApplicationContext的方法
查看>>
UVA 11346 Probability 概率 (连续概率)
查看>>