题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1392
题目大意:平面上有n个点代表n棵树,现在要把这些树用绳子围起来,求最少需要的绳子长度。
分析:简单求凸包问题。
实现代码如下:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; typedef struct { double x,y; }POINT; POINT result[110]; POINT tree[110]; int n,top; double Distance(POINT p1,POINT p2) { return sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ); } double Multiply(POINT p1,POINT p2,POINT p3) { return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x); } int cmp(const void *p1,const void *p2) { POINT *p3,*p4; double m; p3=(POINT *)p1; p4=(POINT *)p2; m=Multiply(tree[0],*p3,*p4); if(m<0) return 1; else if(m==0&&(Distance(tree[0],*p3)<Distance(tree[0],*p4))) return 1; else return -1; } void Tubao() { result[0].x=tree[0].x,result[0].y=tree[0].y; result[1].x=tree[1].x,result[1].y=tree[1].y; result[2].x=tree[2].x,result[2].y=tree[2].y; top=2; for(int i=3;i<=n;i++) { while(Multiply(result[top-1],result[top],tree[i])<=0) top--; result[top+1].x=tree[i].x; result[top+1].y=tree[i].y; top++; } } int main() { int pos; double px,py; while(scanf("%d",&n)!=-1&&n) { py=-1; for(int i=0;i<n;i++) scanf("%lf%lf",&tree[i].x,&tree[i].y); if(n==1) { printf("0.00\n"); continue; } else if(n==2) { printf("%.2lf\n",Distance(tree[0],tree[1])); continue; } for(int i=0;i<n;i++) { if(py==-1||tree[i].y<py) { px=tree[i].x; py=tree[i].y; pos=i; } else if(tree[i].y==py&&tree[i].x<px) { px=tree[i].x; py=tree[i].y; pos=i; } } double tmp=tree[0].x; tree[0].x=tree[pos].x; tree[pos].x=tmp; tmp=tree[0].y; tree[0].y=tree[pos].y; tree[pos].y=tmp; qsort(&tree[1],n-1,sizeof(POINT),cmp); tree[n].x=tree[0].x; tree[n].y=tree[0].y; Tubao(); double len=0.0; for(int i=0;i<top;i++) len+=Distance(result[i],result[i+1]); printf("%.2f\n",len); } return 0; }