zoukankan      html  css  js  c++  java
  • HDU 2440、HDU 3694多边形费马点

    1、http://acm.hdu.edu.cn/showproblem.php?pid=2440   按照题意知道是一个简单的多边形即凸包,但给出的点并没有按照顺序的,所以需要自己先求出凸包,然后在用随机淬火求费马点。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<stack>
    #include<map>
    #include<vector>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    #define eps 1e-10
    
    int Fabs(double d)
    {
        if(fabs(d)<eps) return 0;
        else return d>0?1:-1;
    }
    
    struct point 
    {
        double x,y;
    }p[105],sta[105];
    int oper[8][2]={0,1,0,-1,-1,0,1,0,1,1,1,-1,-1,1,-1,-1},top;
    
    double x_multi(point p1,point p2,point p3)    
    {  
        return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);  
    } 
    
    double Dis(point p1,point p2)
    {
        return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
    }
    
    bool cmp(point a,point b)
    {
        if(Fabs(x_multi(p[0],a,b))>0) return 1;
        if(Fabs(x_multi(p[0],a,b))<0) return 0;
        if(Fabs(Dis(p[0],a)-Dis(p[0],b))<0)
            return 1;
        return 0;
    }
    
    void Graham(int n)
    {
        int i,k=0,tot;
        for(i=1;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[0],p[k]);
        sort(p+1,p+n,cmp);
        
        tot=1;
        for(i=2;i<n;i++)
            if(Fabs(x_multi(p[i],p[i-1],p[0])))
                p[tot++]=p[i-1];
        p[tot++]=p[n-1];
        
        sta[0]=p[0],sta[1]=p[1];
        i=top=1;
        for(i=2;i<tot;i++)
        { 
            while(top>=1&&Fabs(x_multi(p[i],sta[top],sta[top-1]))>=0)
            { 
                if(top==0) break; 
                top--; 
            } 
            sta[++top]=p[i]; 
        }   
    }
    
    double allDis(int n,point f)
    {
        double sum=0.0;
        int i;
        for(i=0;i<n;i++)
            sum+=Dis(sta[i],f);
        return sum;
    }
    
    point fermat(int n) //求费马点
    {
        double step=0;
        int i,j;
        for(i=0;i<n;i++)
            step+=fabs(sta[i].x)+fabs(sta[i].y);
        point f;
        f.x=0,f.y=0;
        for(i=0;i<n;i++)
            f.x+=sta[i].x,f.y+=sta[i].y;
        f.x/=n,f.y/=n;
        point t;
        while(step>eps)
        {
            for(i=0;i<8;i++)
            {
                t.x=f.x+oper[i][0]*step;
                t.y=f.y+oper[i][1]*step;
                if(allDis(n,t)<allDis(n,f))
                    f=t;
            }
            step/=2;
        }
        return f;
    }
    
    int main()
    {
        int t,n,i;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(i=0;i<n;i++)
                scanf("%lf%lf",&p[i].x,&p[i].y);
            Graham(n);
            point ans=fermat(top+1);
            printf("%.0lf
    ",allDis(top+1,ans));
            if(t>0) puts("");
        }
        return 0;
    }

    2、http://acm.hdu.edu.cn/showproblem.php?pid=3694 //求一个四边形的费马点,wrong了n次网上到处查才知道此题非常严谨,卡随机淬火算法。并且给出的四边形并不一定是凸四边形,所以需要讨论,如果是凸四边形,按照四边形的特性费马点就是对角线的交点,如果是凹的就是其中某一个顶点。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<stack>
    #include<map>
    #include<vector>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    #define eps 1e-8
    
    int Fabs(double d)
    {
        if(fabs(d)<eps) return 0;
        else return d>0?1:-1;
    }
    
    struct point 
    {
        double x,y;
    }p[10],sta[10];
    int oper[8][2]={0,1,0,-1,-1,0,1,0,1,1,1,-1,-1,1,-1,-1},top;
    
    double x_multi(point p1,point p2,point p3)    
    {  
        return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);  
    } 
    
    double Dis(point p1,point p2)
    {
        return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
    }
    
    bool cmp(point a,point b)
    {
        if(Fabs(x_multi(p[0],a,b))>0) return 1;
        if(Fabs(x_multi(p[0],a,b))<0) return 0;
        if(Fabs(Dis(p[0],a)-Dis(p[0],b))<0)
            return 1;
        return 0;
    }
    
    void Graham(int n)
    {
        int i,k=0,tot;
        for(i=1;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[0],p[k]);
        sort(p+1,p+n,cmp);
        
        /*tot=1;//下面直接用顶点个数判断是否为凸包,所以这里不去共线点
        for(i=2;i<n;i++)
            if(Fabs(x_multi(p[i],p[i-1],p[0])))
                p[tot++]=p[i-1];
        p[tot++]=p[n-1];*/
        
        sta[0]=p[0],sta[1]=p[1];
        i=top=1;
        for(i=2;i<n;i++)
        { 
            while(top>=1&&Fabs(x_multi(p[i],sta[top],sta[top-1]))>=0)
            { 
                if(top==0) break; 
                top--; 
            } 
            sta[++top]=p[i]; 
        }   
    }
    
    /*double allDis(int n,point f)
    {
        double sum=0.0;
        int i;
        for(i=0;i<n;i++)
            sum+=Dis(p[i],f);
        return sum;
    }
    
    point fermat(int n)
    {
        double step=0;
        int i,j;
        for(i=0;i<n;i++)
            step+=fabs(sta[i].x)+fabs(sta[i].y);
        point f;
        f.x=0,f.y=0;
        for(i=0;i<n;i++)
            f.x+=sta[i].x,f.y+=sta[i].y;
        f.x/=n,f.y/=n;
        point t;
        while(step>1e-10)
        {
            for(i=0;i<8;i++)
            {
                t.x=f.x+oper[i][0]*step;
                t.y=f.y+oper[i][1]*step;
                if(allDis(n,t)<allDis(n,f))
                    f=t;
            }
            step/=2;
        }
        return f;
    }
    */
    int main()
    {
        int i,j;
        while(~scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p[0].x,&p[0].y,&p[1].x,&p[1].y,&p[2].x,&p[2].y,&p[3].x,&p[3].y))
        {
            if(p[0].x==-1&&p[0].y==-1&&p[1].x==-1&&p[1].y==-1&&p[2].x==-1&&p[2].y==-1&&p[3].x==-1&&p[3].y==-1)
                break;
            Graham(4);
            double ans;
            if(top==3)
                ans=Dis(sta[0],sta[2])+Dis(sta[1],sta[3]);//凸四边形就直接取对角线交点
            else 
            {
                ans=1e50;
                double sum=0;
                for(i=0;i<4;i++)
                {
                    sum=0.0;
                    for(j=0;j<4;j++)
                        if(i!=j)
                            sum+=Dis(p[i],p[j]);
                     ans=min(sum,ans);
                }
            }
            printf("%.4lf
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    了解 NoSQL 的必读资料
    关于什么时候用assert(断言)的思考
    这次见到了一些大侠
    NetBeans 时事通讯(刊号 # 87 Jan 12, 2010)
    动态链接库dll,静态链接库lib, 导入库lib
    新女性十得 写得了代码,查得出异常
    记录系统乱谈
    新女性十得 写得了代码,查得出异常
    fullpage.js禁止滚动
    RunningMapReduceExampleTFIDF hadoopclusternet This document describes how to run the TFIDF MapReduce example against ascii books. This project is for those who wants to experiment hadoop as a skunkworks in a small cluster (110 nodes) Google Pro
  • 原文地址:https://www.cnblogs.com/13224ACMer/p/4726854.html
Copyright © 2011-2022 走看看