• Rotational Painting(hdu 3685 凸包+多边形重心 模板题


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3685

    ac代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 50010
    using namespace std;
    const double zero=1e-8;
    struct node
    {
        double x,y;
    }p[maxn],q[maxn];//p保存原始点,q保存凸包的点
    bool operator <(node a,node b)
    {
        if(fabs(a.y-b.y)>zero)//误差
            return (a.y<b.y);
        else if(fabs(a.x-b.x)>zero)
            return (a.x<b.x);
        return false;
    }
    double det(node a,node b,node c)//叉积
    {
        return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
    }
    double dot(node a,node b,node c)//点积
    {
        return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
    }
    double det3(node a,node b,node c)//叉积的三出口函数
    {
        double d=det(a,b,c);
        if(fabs(d)<=zero)return 0;
        if(d<0)return-1;
        return 1;
    }
    void c_h_add(node li[],int &m0,int base,node p)
    {
        while(m0>base&&det3(li[m0-2],li[m0-1],p)<=0)--m0;
        li[m0]=p;
        m0++;
    }
    node c[maxn];
    int n,m;
    void c_h(int &m0)
    {
        int i;
        for(i=0;i<n;i++)
            q[i]=p[i];
        sort(q,q+n);
        m0=0;
        for(i=0;i<n;i++)c_h_add(c,m0,1,q[i]);
        int m1=m0;
        for(i=n-1;i>=0;i--)c_h_add(c,m0,m1,q[i]);
        for(i=0;i<m0;i++)q[i]=c[i];
        m0--;
    }
    bool is_big_angle(node a,node b,node c)//判断以b为顶点的角是否是直角或钝角
    {
        double Lcos=dot(b,a,c);
        if(Lcos>zero)return 0;
        return 1;
    }
    bool check(node zx,node a,node b)//判断zx到直线ab的垂足是否在线段ab上
    {
        return (!is_big_angle(zx,a,b)&&!is_big_angle(zx,b,a));
    }
    int main()
    {
        int t,i,j;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(i=0;i<n;i++)
            {
                scanf("%lf%lf",&p[i].x,&p[i].y);
            }
            node o,o1;
            o.x=o.y=0;
            double s=0,s1;
            for(i=1;i<n-1;i++)
            {
                o1.x=(p[0].x+p[i].x+p[i+1].x);
                o1.y=(p[0].y+p[i].y+p[i+1].y);
                s1=det(p[0],p[i],p[i+1]);
                s+=s1;
                o.x+=o1.x*s1;
                o.y+=o1.y*s1;
            }
            o.x=o.x/s/3.0;//除3放到最后除
            o.y=o.y/s/3.0;//多边形重心
            m=0;
            c_h(m);
            int ans=0;
            for(i=0;i<m-1;i++)
            {
                if(check(o,q[i],q[i+1]))ans++;
            }
            if(check(o,q[m-1],q[0]))ans++;
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

    求多边形重心模板:

    https://www.cnblogs.com/hate13/p/4152302.html

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 50010
    using namespace std;
    const double zero=1e-8;
    struct node
    {
        double x,y;
    }p[maxn],q[maxn];
    double det(node a,node b,node c)//叉积
    {
        return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
    }
    int main()
    {
        int t,i,j,n;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(i=0;i<n;i++)
            {
                scanf("%lf%lf",&p[i].x,&p[i].y);
            }
            node o,o1;
            o.x=o.y=0;
            double s=0,s1;
            for(i=1;i<n-1;i++)
            {
                o1.x=(p[0].x+p[i].x+p[i+1].x);
                o1.y=(p[0].y+p[i].y+p[i+1].y);
                s1=det(p[0],p[i],p[i+1]);
                s+=s1;
                o.x+=o1.x*s1;
                o.y+=o1.y*s1;
            }
            o.x=o.x/s/3.0;
            o.y=o.y/s/3.0;//多边形重心
            printf("%.3f %.3f
    ",o.x,o.y);
        }
        return 0;
    }
    View Code

    求凸包模板:

    https://www.cnblogs.com/wpbing/p/9456240.html

    #include<bits/stdc++.h>
    using namespace std;
    
    struct point{
        double x,y;
        point friend operator -(point a,point b)
        {return {a.x-b.x,a.y-b.y};}
    }p[105],s[105];
    double dis(point a,point b)
    {
        point c=a-b;
        return sqrt(c.x*c.x+c.y*c.y);
    }
    double X(point a,point b)
    {
        return a.x*b.y-a.y*b.x;
    }
    int cmp(point a,point b)
    {
        double x=X(a-p[1],b-p[1]);
        
        if(x>0) return 1;
        if(x==0&&dis(a,p[1])<dis(b,p[1])) return 1;
        return 0;
    }
    double multi(point p1,point p2,point p3)
    {
        return X(p2-p1,p3-p1);
    }
    int main()
    {
        int N;
        while(scanf("%d",&N),N)
        {
            for(int i=1;i<=N;i++) cin>>p[i].x>>p[i].y;
            int k=1;
            for(int i=2;i<=N;i++)
            if(p[i].y<p[k].y||(p[i].y==p[k].y&&p[i].x<p[k].x))k=i;
            swap(p[1],p[k]);
            sort(p+2,p+1+N,cmp);
            s[1]=p[1];
            s[2]=p[2];
            int t=2;
            for(int i=3;i<=N;i++)
            {
                while(t>=2&&multi(s[t-1],s[t],p[i])<=0) t--;
                s[++t]=p[i];
            }
            double sum=0;
            for(int i=1;i<t;i++)
            {
                sum+=dis(s[i],s[i+1]);//s[i]凸包上的每个点 sum周长
            }
            printf("%.2lf
    ",sum+dis(s[1],s[t]));
        }
        return 0;
    }
    View Code

     求凸包(有序 按逆时针或顺时针排序)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    const int maxn=1005;
    const double PI=acos(-1.0);
    
    struct Point{
        int x,y;
        Point():x(0),y(0){}
        Point(int x,int y):x(x),y(y){}
    }list[maxn];
    int stack[maxn],top;
    
    //计算叉积p0p1×p0p2
    int cross(Point p0,Point p1,Point p2){
        return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
    }
    //计算p1p2的距离
    double dis(Point p1,Point p2){
        return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
    }
    //极角排序函数,角度相同则距离小的在前面
    bool cmp(Point p1,Point p2){
        int tmp=cross(list[0],p1,p2);
        if(tmp>0) return true;
        else if(tmp==0&&dis(list[0],p1)<dis(list[0],p2)) return true;
        else return false;
    }
    //输入,把最左下角放在list[0],并且进行极角排序
    void init(int n){
        Point p0;
        scanf("%d%d",&list[0].x,&list[0].y);
        p0.x=list[0].x;
        p0.y=list[0].y;
        int k=0;
        for(int i=1;i<n;++i){
            scanf("%d%d",&list[i].x,&list[i].y);
            if((p0.y>list[i].y)||((p0.y==list[i].y)&&(p0.x>list[i].x))){
                p0.x=list[i].x;
                p0.y=list[i].y;
                k=i;
            }
        }
        list[k]=list[0];
        list[0]=p0;
        sort(list+1,list+n,cmp);
    }
    //graham扫描法求凸包,凸包顶点存在stack栈中
    //从栈底到栈顶一次是逆时针方向排列的
    //如果要求凸包的一条边有2个以上的点
    //那么要将while中的<=改成<
    //但这不能将最后一条边上的多个点保留
    //因为排序时将距离近的点排在前面
    //那么最后一条边上的点仅有距离最远的会被保留,其余的会被出栈
    //所以最后一条边需要特判
    void graham(int n){
        if(n==1){
            top=0;
            stack[0]=0;
            return;
        }
        top=1;
        stack[0]=0;
        stack[1]=1;
        for(int i=2;i<n;++i){
            while(top>0&&cross(list[stack[top-1]],list[stack[top]],list[i])<=0) --top;
            stack[++top]=i;
        }
    }
    int main(){
        int n,t;
        scanf("%d",&t);
        while(t--){
            int id;
            scanf("%d %d",&id,&n);
            init(n);
            graham(n);
            printf("%d %d
    ",id,1+top);
            int kk=0;
            for(int i=1;i<=top;++i)
                if(list[stack[i]].y>list[stack[kk]].y||list[stack[i]].y==list[stack[kk]].y&&list[stack[i]].x<list[stack[kk]].x)kk=i;
    
            for(int i=kk;i>=0;i--)printf("%d %d
    ",list[stack[i]].x,list[stack[i]].y);
            for(int i=top;i>kk;i--)printf("%d %d
    ",list[stack[i]].x,list[stack[i]].y);//顺时针顺序输出每个点
            
            /*
            double res=0;//求凸包周长
        for(int i=0;i<top;++i)
            res+=dis(list[stack[i]],list[stack[i+1]]);
        res+=dis(list[stack[0]],list[stack[top]]);
        printf("%d
    ",(int)(res+0.5));
        */
        }
        return 0;
    }
    graham扫描法
  • 相关阅读:
    Ubuntu oracle SDK替换OpenJDK
    用update-alternatives管理java版本
    安卓配置
    CS 159: Advanced Topics in Machine Learning: Structured Prediction
    ros bag 代码操作
    vim 方式快捷编辑代码
    文件权限
    操作系统连不上网
    github权限管理
    nmap基本命令使用
  • 原文地址:https://www.cnblogs.com/ydw--/p/11372749.html
Copyright © 2020-2023  润新知