格雷厄姆扫描 C++ 不起作用
Posted
技术标签:
【中文标题】格雷厄姆扫描 C++ 不起作用【英文标题】:Graham scan c++ won't work 【发布时间】:2013-06-11 19:26:32 【问题描述】:我的格雷厄姆扫描代码不起作用,它应该得到凸包的周长。它得到n个点的输入,可以有小数。该算法返回一个高于实际周长的值。
我正在使用我的理解: http://en.wikipedia.org/wiki/Graham_scan
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define PI 3.14159265
int nodes;
double xmin=10000000, ymin=10000000, totes=0;
struct ppoint
double x, y, angle;
void anglemake()
angle=atan2(y-ymin, x-xmin)*180/PI;
if(angle<0)
angle=360+angle;
np;
点结构,具有使它与y和x坐标最低的点之间的夹角的函数
vector<ppoint> ch, clist;
bool hp(ppoint i, ppoint j)
return i.angle<j.angle;
double cp(ppoint a, ppoint b, ppoint c)
return ((b.x-a.x)*(c.y-a.y))-((b.y-a.y)*(c.x-a.x));
z 叉积函数
double dist(ppoint i, ppoint j)
double vd, hd;
vd=(i.y-j.y)*(i.y-j.y);
hd=(i.x-j.x)*(i.x-j.x);
return sqrt(vd+hd);
距离发生器
int main()
scanf("%d", &nodes);
for(int i=0; i<nodes; i++)
scanf("%lf%lf", &np.x, &np.y);
if(np.y<ymin || (np.y==ymin && np.x<xmin))
ymin=np.y;
xmin=np.x;
ch.push_back(np);
获得积分
for(int i=0; i<nodes; i++)
ch[i].anglemake();
sort(ch.begin(), ch.end(), hp);
clist.push_back(ch[0]);
clist.push_back(ch[1]);
ch.push_back(ch[0]);
排序并开始格雷厄姆扫描
for(int i=2; i<=nodes; i++)
while(cp(clist[clist.size()-2], clist[clist.size()-1], ch[i])<0)
clist.pop_back();
clist.push_back(ch[i]);
格雷厄姆扫描
for(int i=0; i<nodes; i++)
totes+=dist(clist[i], clist[i+1]);
获取周长
printf("%.2lf\n", totes);
return 0;
【问题讨论】:
相关:Graham scan issue at high amount of points. 【参考方案1】:为了兴趣,在dist求和之前打印出节点和clist.size()的值。
仅当 pop_back 从未发生时,clist 才能拥有节点+1 项。如果是,你有未定义的行为。
【讨论】:
我认为可能是这样。如果将vec[i]
替换为vec.at(i)
,向量将验证索引并抛出异常,这是最小且侵入性最小的更改。除此之外,在c.pop_back()
之前,请确保该元素与assert(!c.empty())
存在。【参考方案2】:
我认为问题出在这里:
for(int i=0; i<nodes; i++)
totes+=dist(clist[i], clist[i+1]);
clist
将只有剩余的点数,而不是 nodes + 1
,这是您加载的点数加一。首先存储这个数字是一个错误恕我直言,因为它从点数开始,然后添加一个以关闭循环,然后再次删除点以使船体凸出。只需使用container.size()
,一切就清楚了。
另一个注意事项:使用经过检查的 C++ 标准库实现进行调试。这些会警告您未定义的行为,例如访问超出其范围的向量。 C++ 是一种语言,它允许您以多种方式自爆,所有这些都以性能为名。这很好,除非在调试时,也就是您想要最好的诊断时。
【讨论】:
以上是关于格雷厄姆扫描 C++ 不起作用的主要内容,如果未能解决你的问题,请参考以下文章