c语言凸包算法,C ++中使用分而治之算法的凸包

在本教程中,我们将讨论一个程序来查找给定点集的凸包。

凸包是最小的多边形凸图,其中包含图内边界上的所有给定点。

在此程序中,我们将使用蛮力将给定的点划分为较小的段,然后最终将随后的段合并以构造凸包。

示例#include

using namespace std;

//存储多边形的中心点

pair mid;

//的象限

//特定点

int quad(pair p){

if (p.first >= 0 && p.second >= 0)

return 1;

if (p.first <= 0 && p.second >= 0)

return 2;

if (p.first <= 0 && p.second <= 0)

return 3;

return 4;

}

//如果线接触多边形

int calc_line(pair a, pair b,

pair c){

int res = (b.second-a.second)*(c.first-b.first) -

(c.second-b.second)*(b.first-a.first);

if (res == 0)

return 0;

if (res > 0)

return 1;

return -1;

}

//比较功能进行排序

bool compare(pair p1, pair q1){

pair p = make_pair(p1.first - mid.first,

p1.second - mid.second);

pair q = make_pair(q1.first - mid.first,

q1.second - mid.second);

int one = quad(p);

int two = quad(q);

if (one != two)

return (one 

return (p.second*q.first 

}

//查找两个多边形的上切线

vector> merger(vector > a,

vector > b){

int n1 = a.size(), n2 = b.size();

int ia = 0, ib = 0;

for (int i=1; i

if (a[i].first > a[ia].first)

ia = i;

//计算b的最左点

for (int i=1; i

if (b[i].first 

ib=i;

int inda = ia, indb = ib;

bool done = 0;

while (!done){

done = 1;

while (calc_line(b[indb], a[inda], a[(inda+1)%n1]) >=0)

inda = (inda + 1) % n1;

while (calc_line(a[inda], b[indb], b[(n2+indb-1)%n2]) <=0){

indb = (n2+indb-1)%n2;

done = 0;

}

}

int uppera = inda, upperb = indb;

inda = ia, indb=ib;

done = 0;

int g = 0;

//计算下切线

while (!done){

done = 1;

while (calc_line(a[inda], b[indb], b[(indb+1)%n2])>=0)

indb=(indb+1)%n2;

while (calc_line(b[indb], a[inda], a[(n1+inda-1)%n1])<=0){

inda=(n1+inda-1)%n1;

done=0;

}

}

int lowera = inda, lowerb = indb;

vector> ret;

//合并两个多边形以获得凸包

int ind = uppera;

ret.push_back(a[uppera]);

while (ind != lowera){

ind = (ind+1)%n1;

ret.push_back(a[ind]);

}

ind = lowerb;

ret.push_back(b[lowerb]);

while (ind != upperb){

ind = (ind+1)%n2;

ret.push_back(b[ind]);

}

return ret;

}

//蛮力算法找到凸包

vector> bruteHull(vector> a){

set >s;

for (int i=0; i

for (int j=i+1; j

int x1 = a[i].first, x2 = a[j].first;

int y1 = a[i].second, y2 = a[j].second;

int a1 = y1-y2;

int b1 = x2-x1;

int c1 = x1*y2-y1*x2;

int pos = 0, neg = 0;

for (int k=0; k

if (a1*a[k].first+b1*a[k].second+c1 <= 0)

neg++;

if (a1*a[k].first+b1*a[k].second+c1 >= 0)

pos++;

}

if (pos == a.size() || neg == a.size()){

s.insert(a[i]);

s.insert(a[j]);

}

}

}

vector>ret;

for (auto e:s)

ret.push_back(e);

//沿逆时针方向移动

mid = {0, 0};

int n = ret.size();

for (int i=0; i

mid.first += ret[i].first;

mid.second += ret[i].second;

ret[i].first *= n;

ret[i].second *= n;

}

sort(ret.begin(), ret.end(), compare);

for (int i=0; i

ret[i] = make_pair(ret[i].first/n, ret[i].second/n);

return ret;

}

//返回凸包的值

vector> divide(vector> a){

if (a.size() <= 5)

return bruteHull(a);

//左包含左半点

//右边包含右边的半点

vector>left, right;

for (int i=0; i

left.push_back(a[i]);

for (int i=a.size()/2; i

right.push_back(a[i]);

vector>left_hull = divide(left);

vector>right_hull = divide(right);

//合并凸包

return merger(left_hull, right_hull);

}

int main(){

vector > a;

a.push_back(make_pair(0, 0));

a.push_back(make_pair(1, -4));

a.push_back(make_pair(-1, -5));

a.push_back(make_pair(-5, -3));

a.push_back(make_pair(-3, -1));

a.push_back(make_pair(-1, -3));

a.push_back(make_pair(-2, -2));

a.push_back(make_pair(-1, -1));

a.push_back(make_pair(-2, -1));

a.push_back(make_pair(-1, 1));

int n = a.size();

sort(a.begin(), a.end());

vector >ans = divide(a);

cout <

for (auto e:ans)

cout <

return 0;

}

输出结果Convex Hull:

-5 -3

-1 -5

1 -4

0 0

-1 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值