zoukankan      html  css  js  c++  java
  • 二维凸包(模板) hdu 1348 求凸包的周长

    题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1348

    凸包模板:

    const int N =1010;
    const double PI = 3.1415927;
    double EPS=1e-10;
    // 考虑误差的加法运算
    double add(double a,double b)
    {
        if(fabs(a+b)<EPS*(fabs(a)+fabs(b))) return 0;
        return a+b;
    }
    struct Point{
        double x,y;
        Point(){}
        Point(double x,double y):x(x),y(y){} // 构造函数,方便代码编写
        Point(const Point & p):x(p.x),y(p.y){}
        Point operator +(Point p){
            return Point(add(x,p.x), add(y,p.y));
        }
        Point operator-(Point p){
            return Point(add(x,-p.x),add(y,-p.y));
        }
        Point operator*(double d){
            return Point(x*d,y*d);
        }
        double operator*(Point p){  // 内积 点乘
            return add(x*p.x, y*p.y);
        }
        double operator^(Point p){//  外积 叉乘
            return add(x*p.y,-y*p.x);
        }
        friend ostream& operator<<(ostream& os,const Point& p ){
            os<<p.x<<" "<<p.y<<endl;
            return os;
        }
        friend istream& operator>>(istream& is, Point& rh) {// Point 不能是常量,是变量
            is>>rh.x>>rh.y;
            return is;
        }
        double dist(Point p){
            return sqrt( add( (x-p.x)*(x-p.x),(y-p.y)* (y-p.y) ) );
        }
    };
    
    Point List[N];   // 输入点集Q
    Point stack[N];  // 栈从低到顶部包含了按逆时针方向排列在CH(Q)(凸包)中的各个顶点。
    int top;   // 栈顶
    
    bool cmp(Point a,Point b)
    {
        if(a.y!= b.y)
            return a.y<b.y;
        else return a.x<b.x;
    }
    // 按极角排序,如果极角相等则按距离从小到大,sort是按从小到大排列的,故需对<符号重载
    bool operator<(Point p1,Point p2)
        {
        double  tmp=(p1-List[0])^(p2-List[0]); //List[0]为基点
        if(tmp>0) return 1;
        else if(tmp==0 && p1.dist(List[0])< p2.dist(List[0])) return 1;
        else return 0;
        }
    
    // 输入点集Q,并把最左下方的点放在 LIst[0],作为基点,
    //并且进行极角排序,对sort(list+1,List+n) ,最大时间O(nlgn)
    void init(int n)
    {
        for(int i=1;i<n;i++)
            cin>>List[i];
        sort(List, List+n,cmp); // List[0] 存储的是 左下方的点
        sort(List+1,List+n);   // 对 List[1]~ List[n-1] 进行对 List[0]的极角排序
    }
    // 寻找凸包 graham 扫描法 时间O(n)
    void graham(int n)
    {
        if(n==1)
            {top=0;
            stack[0]=List[0];}
        if(n==2)
        {
            top=1;
            stack[0]=List[0];
            stack[1]=List[1];
        }
        if(n>2)
        {
            for(int i=0;i<=1;i++)  // 初始化栈,有p0,p1进栈
                stack[i]=List[i];
            top=1;
            for(int i=2;i<n;i++)
            {
                while(top>=1 && ((stack[top]-stack[top-1])^(List[i]-stack[top-1]))<=0) // 非左转
                    top--; // 删除栈顶元素
                top++;
                stack[top]=List[i]; // 将i压入栈
            }
        }
    }
     

    hdu 1348 求凸包的周长 + 圆周长

    http://acm.hdu.edu.cn/showproblem.php?pid=1348

    代码如下:

    #include <iostream>
    #include <algorithm>
    #include <stdlib.h>
    #include <iostream>
    #include <stdio.h>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <set>
    #include <math.h>
    #include <cmath>
    #include <map>
    #include <queue>
    
    using namespace std;
    typedef long long ll;
    
    const int N =1010;
    const double PI = 3.1415927;
    double EPS=1e-10;
    // 考虑误差的加法运算
    double add(double a,double b)
    {
        if(fabs(a+b)<EPS*(fabs(a)+fabs(b))) return 0;
        return a+b;
    }
    struct Point{
        double x,y;
        Point(){}
        Point(double x,double y):x(x),y(y){} // 构造函数,方便代码编写
        Point(const Point & p):x(p.x),y(p.y){}
        Point operator +(Point p){
            return Point(add(x,p.x), add(y,p.y));
        }
        Point operator-(Point p){
            return Point(add(x,-p.x),add(y,-p.y));
        }
        Point operator*(double d){
            return Point(x*d,y*d);
        }
        double operator*(Point p){  // 内积 点乘
            return add(x*p.x, y*p.y);
        }
        double operator^(Point p){//  外积 叉乘
            return add(x*p.y,-y*p.x);
        }
        friend ostream& operator<<(ostream& os,const Point& p ){
            os<<p.x<<" "<<p.y<<endl;
            return os;
        }
        friend istream& operator>>(istream& is, Point& rh) {// Point 不能是常量,是变量
            is>>rh.x>>rh.y;
            return is;
        }
        double dist(Point p){
            return sqrt( add( (x-p.x)*(x-p.x),(y-p.y)* (y-p.y) ) );
        }
    };
    
    Point List[N];   // 输入点集Q
    Point stack[N];  // 栈从低到顶部包含了按逆时针方向排列在CH(Q)(凸包)中的各个顶点。
    int top;   // 栈顶
    
    bool cmp(Point a,Point b)
    {
        if(a.y!= b.y)
            return a.y<b.y;
        else return a.x<b.x;
    }
    // 按极角排序,如果极角相等则按距离从小到大,sort是按从小到大排列的,故需对<符号重载
    bool operator<(Point p1,Point p2)
        {
        double  tmp=(p1-List[0])^(p2-List[0]); //List[0]为基点
        if(tmp>0) return 1;
        else if(tmp==0 && p1.dist(List[0])< p2.dist(List[0])) return 1;
        else return 0;
        }
    
    // 输入点集Q,并把最左下方的点放在 LIst[0],作为基点,
    //并且进行极角排序,对sort(list+1,List+n) ,最大时间O(nlgn)
    void init(int n)
    {
        for(int i=0;i<n;i++)
            cin>>List[i];
        sort(List, List+n,cmp); // List[0] 存储的是 左下方的点
        sort(List+1,List+n);   // 对 List[1]~ List[n-1] 进行对 List[0]的极角排序
    }
    // 寻找凸包 graham 扫描法 时间O(n)
    void graham(int n)
    {
        if(n==1)
            {top=0;
            stack[0]=List[0];}
        if(n==2)
        {
            top=1;
            stack[0]=List[0];
            stack[1]=List[1];
        }
        if(n>2)
        {
            for(int i=0;i<=1;i++)  // 初始化栈,有p0,p1进栈
                stack[i]=List[i];
            top=1;
            for(int i=2;i<n;i++)
            {
                while(top>=1 && ((stack[top]-stack[top-1])^(List[i]-stack[top-1]))<=0) // 非左转
                    top--; // 删除栈顶元素
                top++;
                stack[top]=List[i]; // 将i压入栈
            }
        }
    }
    int main()
    {
        int T,count=0,n;
        double r;
        cin>>T;
        while(T--)
        {
            if(count) cout<<endl;
            count=1;
            cin>>n>>r;
            init(n);
            graham(n);
            double ans=0;
            for(int i=0;i<top;i++)
                ans+=stack[i].dist(stack[i+1]);
            ans+=stack[top].dist(stack[0]);
            ans+=2*PI*r;
            printf("%.0lf
    ",ans);
        }
        return 0;
    }
     
  • 相关阅读:
    hdu 5726 GCD
    codeforces 982C Cut 'em all!
    codeforces 982B Bus of Characters
    codeforces 982A Row
    codeforces 983B XOR-pyramid
    codeforces 979D Kuro and GCD and XOR and SUM
    codeforces 983A Finite or not?
    codeforces 984B Minesweeper
    codeforces 979C Kuro and Walking Route
    codeforces 979B Treasure Hunt
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3623079.html
Copyright © 2011-2022 走看看