标签:
题意:
简单的凸包模板题目
题解:
这里介绍一种求凸包的算法:Graham。(相对于其它人的解释可能会有一些出入,但大体都属于这个算法的思想,同样可以解决凸包问题)
相对于包裹法的n*m时间,Graham算法在时间上有很大的提升,只要n*log(n)时间就够了。它的基本思想如下:
1、首先,把所有的点按照y最小优先,其次x小的优先排序
2、维护一个栈,用向量的叉积来判断新插入的点跟栈顶的点哪个在外围,如果栈顶的点在当前插入的点的左边,那么把栈顶的这个元素弹出,弹出之后不能继续插入下一个点,要继续判断当前插入点跟弹出之后的栈顶的点的位置关系,当当前插入的点在栈顶的那个点的左边时,则可以将要插入的点压到栈中,进入下一个点。
http://blog.csdn.net/bone_ace/article/details/46239187
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; const int N = 1e5+10, M = 30005, mod = 1e9 + 7, inf = 0x3f3f3f3f; typedef long long ll; struct point{ double x,y; point (double x = 0, double y = 0):x(x),y(y) {} friend point operator + (point a,point b) { return point(a.x+b.x,a.y+b.y); } friend point operator - (point a,point b) { return point(a.x-b.x,a.y-b.y); } }p[N],res[N]; double dis(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double dot(point a,point b) { return a.x*b.y-b.x*a.y; } int cmp(point a,point b) { if(a.y==b.y) return a.x<b.x; else return a.y<b.y; } int Graham(point* p,int n,point* res) { sort(p+1,p+n+1,cmp); res[1] = p[1]; res[2] = p[2]; int top = 2,len; for(int i=3;i<=n;i++) { while(top>=2 && dot(p[i] - res[top-1],res[top] - res[top-1])>=0) top--; res[++top] = p[i]; } len = top; for(int i=n;i>=1;i--) { while(top!=len&&dot(p[i]-res[top-1],res[top]-res[top-1])>=0) top--; res[++top] = p[i]; } return top; } int main() { int n; while(scanf("%d",&n)&&n) { for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); if(n==1) { printf("0.00\n");continue; } if(n==2) { printf("%.2f\n",dis(p[1],p[n])); continue; } int m=Graham(p,n,res); double tot=0; for(int i=2;i<=m;i++) tot+=dis(res[i-1],res[i]); printf("%.2f\n",tot); } }
标签:
原文地址:http://www.cnblogs.com/zxhl/p/5255155.html