hdu1392凸包求周长 graham 3种写法
来源:互联网 发布:用户数据分析发展方向 编辑:程序博客网 时间:2024/05/17 20:26
一开始用两边扫的过不去,后来自己加了初始化就过了,郁闷一晚上。。。
凸包求周长。。。
两边扫点
#include<iostream>#include<algorithm>#include<cmath>#define MAX 2000#define eps 1e-9using namespace std;struct points{ double x,y;};points p[MAX];int n,l,res[MAX],top;double mult(points sp,points ep,points op){ return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);}bool cmp(const points &a,const points &b){ if(a.y-b.y==eps)return a.x-b.x<eps; return a.y-b.y<eps; }void graham(){ int i,len; top=1; sort(p,p+n,cmp); if(n==0)return; res[0]=0; if(n==1)return; res[1]=1; if(n==2)return; res[2]=2; for(i=2;i<n;i++) { while(top && mult(p[i],p[res[top]],p[res[top-1]])) top--; res[++top]=i; } len=top; res[++top]=n-2; for(i=n-3;i>=0;i--) { while(top!=len && mult(p[i],p[res[top]],p[res[top-1]])) top--; res[++top]=i; }}double dists(points aa,points bb){ return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));}int main(){ while(scanf("%d",&n)!=EOF && n) { memset(p,0,sizeof(p)); memset(res,0,sizeof(res)); { for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); if(n<2)printf("0.00\n"); else if(n==2)printf("%.2lf\n",dists(p[0],p[1])); else { graham(); double re=0; /* for(int i=0;i<top;i++) { cout<<"..."<<p[res[i]].x<<" "<<p[res[i]].y<<endl; }*/ for(int i=0;i<top;i++) re+=dists(p[res[i]],p[res[(i+1)%(top+1)]]); printf("%.2lf\n",re); } } } return 0; }
用tan来排序那么扫点只用1次,因为tan是单调的
#include<iostream>#include<algorithm>#include<cmath>#define MAX 1000#define eps 1e-12using namespace std;struct points{ double x,y; double atan;};points p[MAX],res[MAX];int n,l,top;double mult(points sp,points ep,points op){ return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);}bool ral(points p1,points p2,points p3){ return (p3.x-p1.x)*(p2.y-p1.y)>=(p2.x-p1.x)*(p3.y-p1.y);}bool cmp(const points &a,const points &b){ if(a.y-b.y==eps||a.y-b.y==0)return a.x-b.x<eps; return a.y-b.y<eps; /* return a.y<b.y||(a.y==b.y&&a.x<b.x);*/ }int cmp2(points a,points b){ return a.atan<b.atan || ( a.atan==b.atan && a.x<b.x );}void graham(){ int i,len; top=1; sort(p,p+n,cmp); /**/ p[0].atan=0; for (int i=1;i<n;i++) p[i].atan=atan2(p[i].y-p[0].y,p[i].x-p[0].x); sort(p,p+n,cmp2); /**/ /* if(n==0)return; res[0]=0; if(n==1)return; res[1]=1; if(n==2)return; res[2]=2;*/ res[0]=p[0]; res[1]=p[1]; for(i=2;i<n;i++) { while(top && ral(res[top-1],res[top],p[i])) top--; res[++top]=p[i]; } /*if(top>2 && ral(res[top-1],res[top],p[i])) top--; len=top; res[++top]=n-2; for(i=n-3;i>=0;i--) { while(top != len && mult(p[i],p[res[top]],p[res[top-1]])) top--; res[++top]=i; }*/}double dists(points aa,points bb){ return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y));}int main(){ while(scanf("%d",&n)!=EOF && n) { for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); if(n<2)printf("0.00\n"); else if(n==2)printf("%.2lf\n",dists(p[0],p[1])); else { graham(); double re=0.0; /*for(int i=0;i<=top;i++) cout<<res[i].x<<" "<<res[i].y<<endl;*/ for(int i=0;i<=top;i++) re+=dists(res[i],res[(i+1)%(top+1)]); printf("%.2lf\n",re); } } return 0; }
还有一种网上的用极坐标交换的写法,标准模板
#include <iostream>#include <math.h>#define MaxNode 1000int stack[MaxNode];int top;struct TPoint{ int x; int y;};TPoint point[MaxNode];void swap(TPoint point[], int i, int j){ TPoint tmp; tmp = point[i]; point[i] = point[j]; point[j] = tmp;}double multi(TPoint p1, TPoint p2, TPoint p0){ return double(p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);}double distance(TPoint p1, TPoint p2){ return sqrt(double(p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));}//qsort的比较函数,如果要从小到大排序,则:参数1>参数2时,return1;int cmp(const void *a, const void *b){ TPoint *c = (TPoint *)a; TPoint *d = (TPoint *)b; double k = multi(*c, *d, point[0]); if(k <= 0) return 1; //k<0说明c在d的逆时针方向,即相对于点p0,c的极角比d大 else return -1; }void grahamScan(int n){ //Graham扫描求凸包 int u=0; //将最左下的点调整到p[0]的位置 for(int i = 1;i <= n - 1;i++) { if((point[i].y < point[u].y) || (point[i].y == point[u].y && point[i].x < point[u].x)) u = i; } swap(point, 0, u); //将p[1]到p[n - 1]按按极角排序,可采用快速排序 qsort(point + 1, n - 1, sizeof(point[0]), cmp); for(int i = 0;i <= 2;i++) stack[i] = i; top = 2; for(int i = 3;i <= n - 1;i++) { while(multi(point[i], point[stack[top]], point[stack[top - 1]]) > 0) top--; top++; stack[top] = i; }}double length(int n){ //已知多边形各顶点的坐标,求其周长 double len; int i; len = 0; for(i = 0;i <= n - 1;i++){ len += (distance(point[stack[i]], point[stack[(i + 1) % n]]));//别忘了模n(处理最后一个点和第一个点的距离) } return len;}int main(){ int i, n; while(scanf("%d", &n) && n ){ for(i = 0;i < n;i++) scanf("%d%d", &point[i].x, &point[i].y); if(n < 2){ printf("0.00\n"); continue; } if(n == 2){ printf("%.2lf\n", distance(point[0], point[1])); continue; } grahamScan(n); printf("%.2lf\n", length(top + 1)); } return 0;}
- hdu1392凸包求周长 graham 3种写法
- hdu1392凸包求周长
- hdu1392(凸包求周长)
- HDU1392 凸包问题求周长 + 裸 + Graham算法
- hdu1392 Surround the Trees (求凸包周长)
- Graham算法(计算凸包周长)
- poj1113Wall 求凸包周长 Graham扫描法
- HDU1392
- HDU1392
- HDOJ 1392 Surround the Trees【凸包周长 Graham扫描】
- POJ 1113 && HDU 1348 Wall (凸包周长 graham扫描法)
- 凸包求面积,周长
- POJ 1113 Wall 凸包求周长
- POJ 1113 Wall (凸包求周长)
- hdu1392 凸包
- HDU1392+凸包
- 凸包:HDU1392(ZJU1453)
- hdu1392-Surround the Trees
- 猫捉老鼠问题系列(三)
- POJ 2528 Mayor's posters 线段树+离散化
- JAVA设计模式创建型模式之建造模式
- mysql 1045错误的解决方法
- gtk,gtkglext安装与eclipse cdt配置
- hdu1392凸包求周长 graham 3种写法
- Ubuntu12.04下安装JDK
- 3行程序搞定SVM分类-用JAVA程序调用LibSVM API 最简单的示例
- 精 挑 细 选
- Android开发之AlertDialog对话框内gallery的应用案例
- word显示在网页上
- spark view precompile
- error: initializing argument 2 of 'void (* signal(int, void (*)(int)))(int)'
- redis.conf配置文件中文版