hdu1392Surround the Trees 凸包

来源:互联网 发布:宁波ug编程培训学校 编辑:程序博客网 时间:2024/06/06 18:59

第一次做凸包,这道题要特殊考虑下,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\n",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;}