hdu1392-Surround the Trees-(凸包)
凸包概念:坐标上有好多好多点,把外围的点连起来,所有点都包括在线上或者里面,此时周长最小。看起来每个角凸出去,简称凸包。
顺序:1.找基点 2.自定义按其他点和基点之间的斜率排序 3.按顺序找出符合条件的点压进凸包集合
https://vjudge.net/problem/HDU-1392
题意:有好多树,从最外围围起来,篱笆要多长?
思路:凸包模板题,记录代码
#include<stdio.h> #include<math.h> #include<algorithm>///sort需要的函数 using namespace std; struct node { int x; int y; }; node p[105]; node tu[105]; int n,top; ///叉积是矢量概念,如果结果大于0,p0p1在p0p2的顺时针方向 double chaji(node p0,node p1,node p2) { ///叉积公式=x1*y2-x2*y1,叉积是矢量概念,如果结果大于0,p0p1在p0p2的顺时针方向 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } ///叉积的绝对值是三个点围成面积的一半 double dis(node p1,node p2) { return sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ); } bool cmp(node p1,node p2)///比较函数,只能两两相比 { double z=chaji(p[0],p1,p2); if( z>0 || (z==0&&dis(p[0],p1)<dis(p[0],p2)) ) return true;///返回真,则p1排在p2前 return false; } void Graham()///从基点开始寻找外围的点 {//葛立恒发明的算法 double z; tu[0]=p[0]; tu[1]=p[1];///这两个点总会放进凸包里 top=1; for(int i=2;i<n;i++) { while( chaji(tu[top-1],tu[top],p[i])<0 )///通过p[i]判断tu[top]是不是符合要求 top--;///top-1,继续判断,直到找到符合条件的top,下面会覆盖掉原来的不符合条件的下标内容 top++; tu[top]=p[i]; } ///最后一个点在基点和倒数第二点的连线之外,必然是凸出去的 } int main() { while(scanf("%d",&n) && n) { for(int i=0;i<n;i++)///输入杂乱无章的各点坐标 scanf("%d%d",&p[i].x,&p[i].y); if(n==1) {printf("0\n");continue;} else if(n==2) {printf("%.2lf\n",dis(p[0],p[1]));continue;} int k=0; for(int i=0;i<n;i++) if( p[k].y>p[i].y || (p[k].y==p[i].y&&p[k].x>p[i].x) ) k=i; ///找基点下标,越下越左的 swap(p[0],p[k]);///目前还没有排序,只要确定基点,其他随便换 sort(p+1,p+n,cmp);///按自定义的排序方法排序 Graham(); double len=0;///算凸包外面的长度 for(int i=0;i<top;i++) len += dis(tu[i],tu[i+1]); len += dis(tu[0],tu[top]); printf("%.2f\n",len); } }