zoukankan      html  css  js  c++  java
  • (模板)[USACO5.1]圈奶牛Fencing the Cows (二维凸包)

    题目链接:https://www.luogu.com.cn/problem/P2742

    求凸包有两种常用算法:
    Graham算法:
    首先将所有点按纵坐标从小到大排序,纵坐标相同则按横坐标从小到大排序,
    排序后的第一个点一定位于凸包上,以第一个点为原点进行极角排序,
    然后维护一个单调栈,如果新进来的点与栈顶两个元素形成凹壳则弹出栈顶,一直进行上述操作直到形成凸壳,
    最后栈中的点即为凸包上的点

    时间复杂度 (O(nlogn))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 100000;
    const double eps = 1e-8;
    
    int n;
    double ans = 0;
    
    struct Point{
    	double x, y;
    }a[maxn];
    
    Point operator + (Point a, Point b){ return (Point){a.x + b.x, a.y + b.y}; }
    Point operator - (Point a, Point b){ return (Point){a.x - b.x, a.y - b.y}; }
    Point operator * (Point a, double b){ return (Point){a.x * b, a.y * b}; }
    Point operator / (Point a, double b){ return (Point){a.x / b, a.y / b}; }
    
    double cross(Point o, Point a, Point b){ return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y); }
    double dis(Point a, Point b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
    
    bool cmpy(Point a, Point b){
    	if(fabs(a.y - b.y) < eps) return a.x < b.x;
    	return a.y < b.y;
    }
    
    bool cmp_angle(Point b, Point c){
    	if(fabs(cross(a[1], b, c)) < eps) return dis(a[1], b) < dis(a[1], c) + eps;
    	if(cross(a[1], b, c) < 0) return 0;
    	else return 1;
    }
    
    Point sta[maxn]; int top = 0;
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	scanf("%d", &n);
    	for(int i = 1 ; i <= n ; ++i){ scanf("%lf%lf", &a[i].x, &a[i].y); }
    	
    	sort(a + 1, a + 1 + n, cmpy);
    	sort(a + 2, a + 1 + n, cmp_angle);
    	
    	sta[++top] = a[1];
    	sta[++top] = a[2];
    	
    	for(int i = 3 ; i <= n ; ++i){
    		while(top > 1 && cross(sta[top - 1], a[i], sta[top]) > eps) --top;
    		sta[++top] = a[i];
    	}
    	
    	for(int i = 2 ; i <= top ; ++i){
    		ans += dis(sta[i], sta[i - 1]);
    	}
    	ans += dis(sta[1], sta[top]); 
    	
    	printf("%.2lf
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    掌握 ActionResult
    EF 的 霸气配置
    MVC 3 数据验证 Model Validation 详解
    Entity Framework 插入数据 解决主键非自增问题
    线程池(C#)
    socket 基础学习
    oracle创建job方法
    C# 任意类型数据转JSON格式
    JDBC(连接数据库的四个主要步骤)
    oracle 存储过程详细介绍(创建,删除存储过程,参数传递等)
  • 原文地址:https://www.cnblogs.com/tuchen/p/14274812.html
Copyright © 2011-2022 走看看