http://www.cnblogs.com/Booble/archive/2011/02/28/1967179.html 可参考
算法流程
1.找横坐标最小的点(有一样的话纵坐标更小的)
2.从这点开始卷包裹 找最靠近外侧的点(通过叉积比较)
(注意一开始设k为0 若k=0随意找个点为其值)
3.找到的点为起点退出
注:为什么第二步的时候不怕找到过延长线的点?因为不可能存在这个点,若有这个点 在上一个点就被选择拓展了
叉积为0时 注意用点积判断 选择最外面那个点
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 #define exp 10e-6 using namespace std; struct point{ double x,y; }; double ans; int start; point a[101]; int visit[101]; int N; double crossdet(double x1,double y1,double x2,double y2) { return x1*y2-x2*y1; } double cross(point A,point B,point C) { return crossdet(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y); //AB*AC } double dotdet(double x1,double y1,double x2,double y2) { return x1*x2+y1*y2; } double dot(point A,point B,point C) { return dotdet(B.x-A.x,B.y-A.y,C.x-A.x,C.y-A.y); //AB dot AC } double dist(point A,point B) { return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); } int sgn(double A) { if(fabs(A)<exp) return 0; else if(A>0) return 1; else return -1; } void input() { ans=0;int sx=40000;int sy=40000; memset(a,0,sizeof(a)); memset(visit,0,sizeof(visit)); for(int i=1;i<=N;i++) { scanf("%lf%lf",&a[i].x,&a[i].y); if(sgn(a[i].x-sx)==-1) { sx=a[i].x;sy=a[i].y; start=i; } else if(sgn(a[i].x-sx)==0&&sgn(a[i].y-sy)==-1) { sx=a[i].x;sy=a[i].y; start=i; } } } void init() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } int FIND(int now) { int k=0; for(int i=1;i<=N;i++) { if(visit[i]==0&&i!=now) { if(k==0) { k=i; } else { int temp=cross(a[now],a[k],a[i]); if(sgn(temp)<0) k=i; if(sgn(temp)==0) { int temp2=dot(a[k],a[now],a[i]); if(sgn(temp2)<0) k=i; } } } } visit[k]=1; return k; } void solve() { int now=start,next; while(1) { next=FIND(now); ans+=dist(a[now],a[next]); now=next; if(next==start) break; } } int main() { // init(); while(cin>>N&&N) { input(); solve(); if(N==2) { ans=dist(a[1],a[2]); } if(N==1) ans=0; printf("%.2lf\n",ans); } return 0; }