hdoj1392
Problem : 1392 ( Surround the Trees ) Judge Status : Accepted
RunId : 2853191 Language : C++ Author : huwenbiao
Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta
RunId : 2853191 Language : C++ Author : huwenbiao
Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta
/***************************************************************\
*Author:Hu Wenbiao
*Created Time: Sat 21 Aug 2010 10:33:05 AM CST
*File Name: main.cpp
*Description:几何题目。凸包问题。Graham's scan处理
\***************************************************************/
//*========================*Head File*========================*\\
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
/*----------------------*Global Variable*----------------------*/
struct POINT{
int x,y;
}P[40000];
int Q[40000];
int top,n;
//*=======================*Main Program*=======================*//
using namespace std;
int cmp(const void* i,const void* j){//如果0->i->j是左转,则i在前
POINT *a=(POINT*)i,*b=(POINT*)j;
int tmp=(a->x-P[0].x)*(b->y-P[0].y)-(a->y-P[0].y)*(b->x-P[0].x);
if(tmp>0)
return -1;
else if(tmp<0)
return 1;
else{//如果0->i->j在一条直线上,到0距离小的在前,其实只当出现了
//排好序后0->1->2在一条直线上这种情况,这个讨论才是必要的,
//这种情况其实本题数据中没有出现。
int dx=a->x-P[0].x,dy=a->y-P[0].y;
int da=dx*dx+dy*dy;
dx=b->x-P[0].x,dy=b->y-P[0].y;
int db=dx*dx+dy*dy;
return da-db;
}
}
int cross(int a,int b,int c){//返回(P[a],P[b]),(P[a],P[c])的叉积
int x1=P[b].x-P[a].x,y1=P[b].y-P[a].y;
int x2=P[c].x-P[a].x,y2=P[c].y-P[a].y;
return x1*y2-y1*x2;
}
int main(){
//freopen("input","r",stdin);
while(scanf("%d",&n)!=EOF&&n){
int _min=0;//P[_min]是最下方的点,如果有y相同的情况,取最左边的点
for(int i=0;i<n;i++){
scanf("%d%d",&P[i].x,&P[i].y);
if(P[i].y<P[_min].y)
_min=i;
else if(P[i].y==P[_min].y&&P[i].x<P[_min].x)
_min=i;
}
if(n==1){
printf("0.00\n");
continue;
}
else if(n==2){
printf("%.2lf\n",sqrt(1.0*(P[0].x-P[1].x)*(P[0].x-P[1].x)+(P[0].y-P[1].y)*(P[0].y-P[1].y)));
continue;
}
swap(P[0],P[_min]);
qsort(&P[1],n-1,sizeof(POINT),cmp);
top=0;
Q[top++]=0;
Q[top++]=1;
for(int i=2;i<n;i++){
while(cross(Q[top-2],Q[top-1],i)<=0)//右转或在一条直线上
top--;
Q[top++]=i;
}
//别忘了这种情况
double ans=sqrt(1.0*(P[Q[top-1]].x-P[Q[0]].x)*(P[Q[top-1]].x-P[Q[0]].x)+(P[Q[top-1]].y-P[Q[0]].y)*(P[Q[top-1]].y-P[Q[0]].y));
for(int i=1;i<top;i++){
ans+=sqrt(1.0*(P[Q[i]].x-P[Q[i-1]].x)*(P[Q[i]].x-P[Q[i-1]].x)+(P[Q[i]].y-P[Q[i-1]].y)*(P[Q[i]].y-P[Q[i-1]].y));
}
printf("%.2lf\n",ans);
}
}