凸包
来源:互联网 发布:after school知乎 编辑:程序博客网 时间:2024/04/29 06:24
初学凸包,到百度百科上面搜了一下,发现还是很好理解的。。。。看着上面的代码敲了一遍,,,发现上面的代码有BUG。。。。
下面是自己写的:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <algorithm>#include <map>#include <vector>#include <cmath>using namespace std;int n,top;typedef struct{ double x; double y;} POINT;POINT result[102];POINT g[102];double Multi(POINT c,POINT a,POINT b){ return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);}double Dis(POINT a,POINT b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}bool cmp(const POINT a,const POINT b){ double m = Multi(g[0],a,b); if(m < 0)return 0; else if(m == 0 && Dis(g[0],a) < Dis(g[0],b))return 0; else return 1;}void Tubao(){ result[0].x = g[0].x; result[0].y = g[0].y; result[1].x = g[1].x; result[1].y = g[1].y; top = 1; for(int i = 2; i <= n; i++) { while(Multi(result[top - 1],result[top],g[i]) <= 0 && top > 1) top --; top ++; result[top].x = g[i].x; result[top].y = g[i].y; }}int main(){// freopen("in.txt","r",stdin); while(~scanf("%d",&n)) { int p ; double dx,dy = 100000; for(int i = 0; i < n; i++) { scanf("%lf%lf",&g[i].x,&g[i].y); if(g[i].y < dy) { dy = g[i].y; dx = g[i].x; p = i; } else if(g[i].y == dy && g[i].x < dx) { dx = g[i].x; p = i; } } swap(g[0].x,g[p].x); swap(g[0].y,g[p].y); sort(g + 1,g + n,cmp); g[n].x = g[0].x; g[n].y = g[0].y; Tubao(); double len = 0; for(int i = 0; i < top; i ++) { len += Dis(result[i],result[i+1]); } printf("len = %.2lf\n",len); } return 0;}
自己想了个测例:
60 -12 0.51 1-1 0.51 01 0.5
80 -20 22 00.5 0-0.5 0.2-2 0-1 01 0
跑出来是:len = 7.48;len = 11.31
而用百度百科上面的跑出来却是: len = 7.51;len= 11.72
(是对是错把路径打出来就知道。。。。)
下面是百度上面的代码(代码一):
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <algorithm>#include <map>#include <vector>#include <cmath>using namespace std;typedef struct{ double x; double y;} POINT;POINT result[102];//保存凸包上的点,相当于所说的栈SPOINT a[102];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 Compare(const void*p1,const void*p2)//根据p0->p1的极值和p0->p2的极值进行比较,如果极值相同则用距离长度比较{ POINT *p3,*p4; double m; p3=(POINT*)p1; p4=(POINT*)p2; m=Multiply(a[0],*p3,*p4); if(m<0)return 1; else if(m==0&&(Distance(a[0],*p3)<Distance(a[0],*p4))) return 1; else return -1;}//寻找凸包的过程,p0,p1,p2..的寻找过程在下面main中进行了void Tubao(){ int i; result[0].x=a[0].x; result[0].y=a[0].y; result[1].x=a[1].x; result[1].y=a[1].y; result[2].x=a[2].x; result[2].y=a[2].y; top=2; for(i=3; i<=n; i++) { while(Multiply(result[top-1],result[top],a[i])<=0&&top>2) top--; result[top+1].x=a[i].x; result[top+1].y=a[i].y; top++; }}int main(){// freopen("in.txt","r",stdin); int i,p; double px,py,len,temp; while(scanf("%d",&n)!=EOF) { for(i=0; i<n; i++) scanf("%lf%lf",&a[i].x,&a[i].y); if(n==1) { printf("0.00/n"); continue; } else if(n==2) { printf("%.2lf/n",Distance(a[0],a[1])); continue; }//这里的目的好像是找出y坐标最小的点,之后把他定义为P0 py=-1; /************* 排序这有问题 *************/ for(i=0; i<n; i++) { if(py==-1||a[i].y<py) { px=a[i].x; py=a[i].y; p=i; } else if(a[i].y==py&&a[i].x<px) { px=a[i].x; py=a[i].y; p=i; } }//swap(a[0],a[p]) temp=a[0].x; a[0].x=a[p].x; a[p].x=temp; temp=a[0].y; a[0].y=a[p].y; a[p].y=temp;//用叉乘来实现排序的比较 qsort(&a[1],n-1,sizeof(double)*2,Compare); a[n].x=a[0].x; a[n].y=a[0].y;//调用tubao() Tubao(); len=0.0; for(i=0; i<top; i++) { len=len+Distance(result[i],result[i+1]); } printf("%.2lf\n",len); } return 0;}
分析:上面的代码之所以错是因为在排序的时候没有处理好,,,另外在找凸包顶点的时候也有问题(函数Tubao())。。。。
(看来以后找代码看的注意了。。。)
0 0
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包。
- 凸包
- { 凸包 }
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包
- 凸包
- Science上发表的简单快速的聚类方法
- 使用GitBash记住在新浪Sae上Git仓库的帐号密码,以后再也不用输帐号密码啦!
- 裸机篇 -- S5PV210的中断体系
- 卡马克揭开VR延迟背后的真相
- Tiny4412裸机程序,按键检测(轮询方式)
- 凸包
- iOS学习笔记
- Webkit分析传入的url到真正网络模块发起加载请求
- 1116text(推拉门)
- 15,多文件开发
- Android开发笔记--UI界面(不断更新)
- Windows编程基础程序
- 运算符-java
- javaSE基础入门学习笔记1