hdu1392.Surround the Trees凸包

原题链接

题意:给你n个点,求它的凸包面积

解法:经典Andrew算法,不过需要注意当n=2的时候是一条直线,那么计算就是两点之间的距离。n=1答案是0.00,_不然就会喜提wawawa

#include<bits/stdc++.h>
#define ll long long
#define x first
#define y second
using namespace std;
const int maxn = 1e4 + 10;
int n;
double eps = 1e-8;
struct Point{
    double x,y;
    Point(){}
    Point(double a, double b){
        x = a;
        y = b;
    }
};
int dcmp(double x, double y){
    //通过除去相减的浮点误差
    if(fabs(x-y)<eps)return 0;
    if(x < y)return - 1;
    return 1;
}
int sgn(double x){
        if(fabs(x) < eps){
            return 0;
        }
        if(x < 0)return -1;
        return 1;
}
bool operator == (Point a,Point b){
        return sgn(b.x-a.x) == 0 && sgn(b.y-a.y)==0;
}
bool operator < (Point a,Point b){
        //最左下角
        return sgn(b.y-a.y) == 0 ? sgn(b.x-a.x)<0:b.y<a.y;
}
Point operator - (Point a,Point b){
return Point(b.x-a.x,b.y-a.y);
}
Point operator + (Point a,Point b){
        //向量加
        return Point(b.x+a.x,b.y+a.y);
}
double operator *(Point a,Point b){
        //点乘
        return b.x*a.x+b.y*a.y;
}
double operator ^(Point a,Point b){
        //叉积
        return b.x*a.y-b.y*a.x;
}
Point operator /(double k,Point a){
        return Point(a.x/k,a.y/k);
}
double cross(Point A, Point B){
    return A.x*B.y-A.y*B.x;
}
//A,B直线上一点 C为另外一点
int relation(Point a,Point b,Point c){
    //-1 为左边 1为右边 0在直线上
    int d = sgn(cross((b-a),(c-a)));
    if(d < 0)return 1;
    else if(d > 0)return -1;
    return 0;
}
bool cmp(Point a, Point b){
    if(a.x == b.x)return a.y < b.y;
    return a.x < b.x;
}
double get_dist(Point a, Point b){
    double dx = a.x-b.x;
    double dy = a.y-b.y;
    return sqrt(dx*dx+dy*dy);
}
Point a[maxn];
int stk[maxn];
int top;
bool vis[maxn];
double andrew(){
	top = 0;
    for(int i = 0; i < n; i++){
        //第一次从左往右更新
        //如果当前的点在栈顶向量的左侧 记当前求出relation <= 0说名此时点在向量的左侧或者直线上
        while(top >= 2 && relation(a[stk[top - 1]],a[stk[top]],a[i]) <= 0){
            //当relation==0时此时当前点在直线上 不能进行删除标记
            if(relation(a[stk[top-1]],a[stk[top]],a[i]) < 0)
            vis[stk[top--]] = false;
            else top--;
        }
        stk[++top] = i;
        vis[i] = true;
    }
    vis[0] = false; //把起点标记为0 那么从右往左的时候就可以进行了
    for(int i = n-1; i >= 0; i--){
        if(vis[i])continue;
        while(top >= 2 && relation(a[stk[top-1]],a[stk[top]],a[i]) <= 0){
            top--;
        }
        stk[++top] = i;
    }
    double ans = 0.0;
    for(int i = 2; i <= top; i++){
        ans += get_dist(a[stk[i]],a[stk[i - 1]]);
    }
    return ans;
}
int main(){
//	freopen("2.in","r",stdin);
    while(scanf("%d",&n)!=EOF){
    if(n == 0)break;
    for(int i = 0; i < n; i++){
        double x,y;
        scanf("%lf%lf",&x,&y);
        a[i] = Point(x,y);
    }
    sort(a,a+n);
    if(n == 1){
    	printf("0.00\n");
    	continue;
	}
    if(n == 2){
    	double ans = 0.0;
    	ans = get_dist(a[0],a[1]);
    	printf("%.2lf\n",ans);
    	continue;
	}
    printf("%.2lf\n",andrew());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值