初学凸包(凸包学习总结)
来源:互联网 发布:unity3d water 编辑:程序博客网 时间:2024/05/21 15:41
前言:
这几天一直在网上听清华大学的一门课叫《计算几何》,感觉老师讲的特别好,听到凸包了,这几天一直在想这个东西,却迟迟写不出代码,感觉还是太浮躁了,没有定下心来,所以在此总结一下凸包的学习以及相关的代码;还有就是关于向量方面接触太少了,估计还要恶补一下与向量有关的数据结构的基础知识。
正文:
补充知识:p叉乘q如果小于0,p在q的逆时针方向,如果大于0,p在q的顺时针方向。等于0共线。(toleft测试需要用到)
凸包:
凸包(Convex Hull)是一个计算几何(图形学)中的概念。在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,...Xn)的线性组合来构造.在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有点的。
计算凸包的算法:Graham算法:这个算法是由数学大师葛立恒(Graham)发明的,他曾经是美国数学学会(AMS)主席、AT&T首席科学家以及国际杂技师协会(IJA)主席。(杂技协会主席,不学点杂技出门都不好意思说自己是程序员)
该算法的复杂度为O(nlgn);
代码:
#include<stdio.h> #include<math.h>#include<algorithm> #define eps 1e-10 #define pi 3.1415926535898 #define N 1010 /* point[]:输入的点集 ch[]:输出的凸包上的点集,按照逆时针方向排列 n:point中的点的数目 len:输出的凸包上的点的个数 */ struct node { double x,y; }point[N],ch[N]; int n,len; double multi(node a,node b,node c) //a在cb左边则小于0 ,a在cb的右边则大于0 { return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x); } double dis(node a,node b) //距离相同去最短 { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void graham_scan(node point[N],node ch[N],int n) { int i,j,k,top; struct node t; k=0; //找到最下且偏左的那个点 for(i=1;i<n;i++) if(point[i].y<point[k].y||(point[i].y==point[k].y&&(point[i].x<point[k].x))) k=i; t=point[0];//将这个点指定为point[0]; point[0]=point[k]; point[k]=t; //按极角从小到大,距离偏短进行排序 for(i=1;i<n-1;i++) { k=i;//选择排序,每次至少找到一个极角最小的点 for(j=i+1;j<n;j++) if(multi(point[j],point[k],point[0])>0||(fabs(multi(point[j],point[k],point[0]))<=eps&& //multi为toleft检测,如果大于0说明被测的在右边极角小 (dis(point[0],point[j])<dis(point[0],point[k])))) k=j; //k保存极角最小的那个点,或者相同距离原点最近 t=point[i]; point[i]=point[k]; point[k]=t; } //第三个点先入栈 ch[0]=point[0]; ch[1]=point[1]; ch[2]=point[2]; top=2; //判断与其余所有点的关系 for(i=3;i<n;i++) { //不满足向左转的关系,栈顶元素出栈 while(multi(point[i],ch[top],ch[top-1])>0||fabs(multi(point[i],ch[top],ch[top-1]))<=eps) top--; //当前点与栈内所有点满足向左关系,因此入栈 ch[++top]=point[i]; } len=top+1; } int main() { int i; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) scanf("%lf%lf",&point[i].x,&point[i].y); graham_scan(point,ch,n); for(i=0;i<len;i++) printf("%lf %lf\n",ch[i].x,ch[i].y); } return 0; }
补充代码:
1 0
- 初学凸包(凸包学习总结)
- 凸包初学(POJ1113)
- 凸包初学整合
- 凸包初学整合
- 初学ROS--"joy"包学习
- 学习凸包(三):凸包练习 POJ 1113
- 凸包学习笔记
- [BZOJ2829]信用卡凸包(凸包)
- 初学Design包
- javascript闭包学习总结
- 学习总结 javascript 闭包
- JavaScript闭包--学习总结
- poj2595(凸包)
- hdu_1348_Wall(凸包)
- poj2187(凸包)
- poj1113(凸包)
- poj3246(*凸包)
- poj2187(凸包)
- 惰性求值和yield-Python
- Java基础知识总结(二)
- 181_08_IO流_FileInputStream_01
- 通过GDB调试理解GOT/PLT
- 没事玩玩leetcode周赛 #30~#34 #40 #42~#48 #50~#54 #56 #58 #59 60 #61
- 初学凸包(凸包学习总结)
- JavaScript学习笔记32-利用循环遍历数组元素
- 使用JDK自带的工具wsimport解析WSDL文件
- JS原生事件中this的指向
- 输入mysql密码正确,却报错1045(2800)
- 创建型设计模式之Builder模式
- JavaScript 10分钟入门
- Unity3D游戏学习笔记3
- HTML中disabled和readonly的区别