zoukankan      html  css  js  c++  java
  • hdu1392 Surround the Trees 凸包

    第一次做凸包,这道题要特殊考虑下,n=2时的情况,要除以二才行。

    我是从最左边的点出发,每次取斜率最大的点,一直到最右边的点。

    然后从最左边的点出发,每次取斜率最低的点,一直到最右边的点。

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    const double eps=1e-9;
    struct node
    {
    	double x,y;
    }f[105];
    bool flag[105];
    int n;
    bool cmp(node a,node b)
    {
    	return fabs(a.x-b.x)<eps?(a.y<b.y):(a.x<b.x);
    }
    double xielv(int a,int b)//求斜率
    {
    	return (f[a].y-f[b].y)/(f[a].x-f[b].x);
    }
    double dis(int a,int b)//求距离
    {
    	double xx=f[a].x-f[b].x,yy=f[a].y-f[b].y;
    	return sqrt(xx*xx+yy*yy);
    }
    void calans()//计算最短周长
    {
    	int i,j,now=0,maxi;
    	double ans=0;
    	while(1)
    	{
    		double max=-4000000;//斜率最大值
    		maxi=now;
    		for(i=1;i<n;i++)
    		{
    			if(flag[i])continue;
    			if(-f[i].x+f[now].x>eps)continue;//在当前点的左边,不考虑
    			if(fabs(f[now].x-f[i].x)<eps)
    			{
    				if(f[now].y>f[i].y)//在当前点的正下方,不考虑
    				  continue;
    		        maxi=i;
    		        break;
    			}
    			else
    			{
    				double p=xielv(now,i);
    				if(p>max)
    	            {
    	            	maxi=i;
    	            	max=p;
    	            }
    			}
    		}
    		flag[maxi]=1;
    		ans+=dis(now,maxi);
    		if(maxi==now)
    		{
    		  flag[maxi]=0;//最后右边的点要计算两次,去除标记
    		  break;
    		}
    		now=maxi;
    	}
    	now=0;
    	while(1)//每次取斜率最小的点
    	{
    		double min=4000000;
    		int mini=now;
    		for(i=1;i<n;i++)
    		{
    			if(flag[i])continue;
    			if(-f[i].x+f[now].x>eps)continue;//在当前点的左边,不考虑
    
    			if(fabs(f[i].x-f[now].x)<eps)
    			{
    				if(f[i].x+0.1<f[n-1].x)//在当前点的正下方,不考虑
    
    				   continue;
                    mini=i;
                    break;
    			}
    				double p=xielv(now,i);
    				if(p<min)
    	            {
    	            	mini=i;
    	            	min=p;
    	            }
    		}
    		ans+=dis(now,mini);
    		flag[mini]=1;
    	    if(mini==now)
    	       break;
    		now=mini;
    	}
    	if(n==2)ans/=2;//n=2时,除以二
    	printf("%.2f
    ",ans);
    }
    int main()
    {
    	int i,j;
    	while(scanf("%d",&n)!=-1&&n)
    	{
    		memset(flag,0,sizeof(flag));
    		for(i=0;i<n;i++)
    		  scanf("%lf%lf",&f[i].x,&f[i].y);
            sort(f,f+n,cmp);
    	    calans();
    	}
    	return 0;
    }


  • 相关阅读:
    将博客搬至CSDN
    linux一部分常用的命令
    java实现qq邮箱每天定时发送邮件
    面向接口编程的小例子
    解决安装mysql的”A Windows service with the name MySQL already exists.“问题
    SpringCloud 随笔
    博客文章链接
    LocalDate与Date转化
    maven的配置以及使用
    windows系统下nginx+tomcat+redis做负载均衡和session粘滞附整套解决方案
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3148244.html
Copyright © 2011-2022 走看看