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;
    }
    
  • 相关阅读:
    游标cursor
    SQL: EXISTS
    LeetCode Reverse Integer
    LeetCode Same Tree
    LeetCode Maximum Depth of Binary Tree
    LeetCode 3Sum Closest
    LeetCode Linked List Cycle
    LeetCode Best Time to Buy and Sell Stock II
    LeetCode Balanced Binary Tree
    LeetCode Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/tuchen/p/14274812.html
Copyright © 2011-2022 走看看