zoukankan      html  css  js  c++  java
  • 凸包

    模版题: http://acm.hdu.edu.cn/showproblem.php?pid=1392(Graham算法)

    #include<bits/stdc++.h>
    using namespace std;
    const int M=1e3+3;
    struct tu{
        double x,y;
        tu friend operator -(tu a,tu b){
            return {a.x-b.x,a.y-b.y};
        }
    }p[M],s[M];
    double X(tu a,tu b){
        return a.x*b.y-a.y*b.x;
    }
    double dis(tu a,tu b){
        a=a-b;
        return sqrt(a.x*a.x+a.y*a.y);
    }
    bool cmp(tu a,tu b){
        int x=X(a-p[1],b-p[1]);
        if(x>0||x==0&&dis(a,p[1])<dis(b,p[1]))
            return 1;
        return 0;
    }
    
    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;
            if(n==1){
                printf("0.00
    ");
                continue;
            }
            else if(n==2){
                printf("%.2lf
    ",dis(p[1],p[2]));
                continue;
            }
            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 tot=2;
            for(int i=3;i<=n;i++){
                while(tot>=2&&X(s[tot]-s[tot-1],p[i]-s[tot-1])<=0)
                    tot--;
                s[++tot]=p[i];
            }
    
            double ans=dis(s[1],s[tot]);
           /// cout<<ans<<endl;
            for(int i=2;i<=tot;i++)
                ans+=dis(s[i],s[i-1]);
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
    View Code

     任意多边形的面积

    struct tu {
        double x, y;
    };
    
    //计算任意多边形的面积,顶点按照顺时针或者逆时针方向排列
    double polygon_area(tu *p, int n)
    {
        if(n < 3) return 0;
    
        double sum = 0;
        p[n + 1] = p[1];
        for(int i = 1; i <= n; i++)
            sum += p[i].x * p[i + 1].y - p[i].y * p[i + 1].x;//可以理解为不管这个多边形在哪,都以原点为分割点,就算原点在外面也可以算出,因为有正负可以抵消掉多余的
        sum = fabs(sum / 2.0);
        return sum;
    }

    求面积均匀的多边形重心

    #include<bits/stdc++.h>
    using namespace std;
    struct node{
        double x,y;
        node friend operator -(node a,node b)
        {
            return {a.x-b.x,a.y-b.y};
        }
        double friend operator *(node a,node b)//对*进行重载  node*node 相当于X乘 
        {
            return a.x*b.y-a.y*b.x;
        }
    }a[1000010];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
            
            double S=0,X=0,Y=0;
            for(int i=2;i<n;i++)
            {
                double x=(a[i]-a[1])*(a[i+1]-a[1]);//这个乘和下面的不一样,这时X乘,求出三角形面积 
                X+=(a[1].x+a[i].x+a[i+1].x)*x;//重心(没除以3)乘以面积 
                Y+=(a[1].y+a[i].y+a[i+1].y)*x;
                S+=x;
            }
            printf("%.2lf %.2lf
    ",X/S/(double)3,Y/S/(double)3);//除以3为重心 
         } 
        return 0;
    }
    View Code

    Melkman算法

    例题:http://poj.org/problem?id=2187

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int M=1e5+5;
    struct node{
        ll x,y;
        node friend operator-(node a,node b){
            return {a.x-b.x,a.y-b.y};
        }
        bool friend operator==(node a,node b){
            return a.x==b.x&&a.y==b.y;
        }
        
    }a[M],p[M<<1];
    bool cmp(node a,node b){
        return a.x-b.x<0||a.x==b.x&&a.y-b.y<0;
    }
    ll dis(node a,node b){
        node c=a-b;
        return c.x*c.x+c.y*c.y;
    }
    ll X(node a,node b){
        return a.x*b.y-a.y*b.x;
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lld%lld",&a[i].x,&a[i].y);
        sort(a,a+n,cmp);
        n=unique(a,a+n)-a;
        int m=0;
        for(int i=0;i<n;i++){
            while(m>1&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0)
                m--;
            p[m++]=a[i];
        }
        int k=m;
        for(int i=n-2;i>=0;i--){
            while(m>k&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0)
                m--;
            p[m++]=a[i];
        }
        n=m;
        if(n>1)
            n--;
        if(n==1)
            return puts("0"),0;
        if(n==2)
            return printf("%lld
    ",dis(p[0],p[1])),0;
        ll ans=0;
        p[n]=p[0];
        int j=1;
        for(int i=0;i<n;i++){
            while(X(p[i+1]-p[i],p[j]-p[i])-X(p[i+1]-p[i],p[j+1]-p[i])<0)
                j=(j+1)%n;
            ll d1=dis(p[i],p[j]);
            ll d2=dis(p[i+1],p[j]);
            ans=max(ans,max(d1,d2));
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    https://codeforces.com/gym/101635 

    分析:旋转卡壳求最小直径

    #include<bits/stdc++.h>
    using namespace std;
    const int M=2e5+5;
    struct  node{
        double x,y;
        node friend operator -(node a,node b){
            return {a.x-b.x,a.y-b.y};
        }
        bool friend operator ==(node a,node b){
            return a.x==b.x&&a.y==b.y;
        }
     
    }a[M],p[M<<1];
    bool cmp(node a,node b){
        return a.x-b.x<0||a.x==b.x&&a.y-b.y<0;
    }
    double X(node a,node b){
        return a.x*b.y-a.y*b.x;
    }
    
    double dis(node a,node b){
        node c=a-b;
        return c.x*c.x+c.y*c.y;
    }
    int main(){
        int n;
        double R;
        scanf("%d%lf",&n,&R);
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&a[i].x,&a[i].y);
        }
        sort(a,a+n,cmp);
        n=unique(a,a+n)-a;
        //cout<<n<<endl;
        int m=0;
        for(int i=0;i<n;i++){
            while(m>1&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0)
                m--;
            p[m++]=a[i];
        }
        int k=m;
        for(int i=n-2;i>=0;i--){
            while(m>k&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0)
                m--;
            p[m++]=a[i];
        }
        if(n>1)
            m--;
        n=m;
        if(n<=2)
            return printf("0.000000000"),0;
        int j=1;
        double ans=2.0*R;
        p[n]=p[0];
        for(int i=0;i<n;i++){
            while(X(p[i+1]-p[i],p[j+1]-p[i])-X(p[i+1]-p[i],p[j]-p[i])>0)///每次找离直线i-i+1最远的点,也即为符合条件的点 
                j=(j+1)%n;
            double d=sqrt(dis(p[i],p[i+1]));
            double h=1.0*fabs(X(p[i+1]-p[i],p[j]-p[i]))/d;
            ans=min(ans,h);
        }
        printf("%.10f
    ",ans);
        return 0;
    }
    Mlekman算法
  • 相关阅读:
    javascript 字符串截取
    HTML5 转
    Javascript try catch finally
    C#之json字符串转xml字符串
    AspNetCore Json序列化设置
    类加载(对象创建)顺序
    线性表,线性表和链表的区别
    Implement int sqrt(int x).
    Add Binary
    Roman to Integer(将罗马数字转成整数)
  • 原文地址:https://www.cnblogs.com/starve/p/11965799.html
Copyright © 2011-2022 走看看