我的格雷厄姆扫描代码不起作用,应该得到凸包的周长。它获得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-cross乘积函数
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]);
排序并启动Graham Scan
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;
}
答案 0 :(得分:1)
只是为了兴趣,在dist summming之前打印出节点和clist.size()的值。
只有pop_back永远不会发生时,clist才能拥有节点+ 1项。如果确实存在未定义的行为。
答案 1 :(得分:0)
我认为问题在于:
for(int i=0; i<nodes; i++)
{
totes+=dist(clist[i], clist[i+1]);
}
clist
只有剩余的点数,而不是nodes + 1
,这是您加载的点数加一。首先存储这个数字是一个错误恕我直言,因为它从点数开始,然后你添加一个来关闭循环,然后再次删除点以使船体凸起。只需使用container.size()
,一切都很清楚。
还有一点需要注意:使用已检查的C ++标准库实现进行调试。这些会警告你未定义的行为,比如访问超出其范围的向量。 C ++是一种语言,它允许你以各种方式射击自己,所有这些都是以表现的名义。这很好,除非在调试时,这是您希望获得最佳诊断的时候。