什么是凸包?
我的理解就是,圖形任意兩點的連線都沒有在圖形外部。
問題:給定點集,怎么求出凸包的邊界點呢???
第一步:給這些點按照X的從大到小進行排序,如果X相同的按照Y再排序。
第二步:把X最小的和最大的連起來,他們必為凸包的邊界點。

第三步:把平面區域分為兩個部分,分別在上面和下面去找面積最大的三角形(面積最大包括的點也就越多嘛,所以適合當凸包的邊界點)

那面積怎么求呢?
求三角形的面積,假設三個點,A(x1,y1),B(x2,y2), C(x3,y3),以下行列式對於平面上任意三角形, 求解面積都很方便, 所得結果是三角形ABC面積的兩倍,A->B->C為順時針順序時,該值為正,,反之則為負。

第四步:進行遞歸,把三角形左邊那個邊作為底邊又去找面積最大的三角形,同理右邊,下面也一樣。
上代碼!!!
#include <iostream>
using namespace std;
#include <algorithm>
#include <stdlib.h>
#define N 10000
int n = 0;
struct POINT
{
int x, y;
}p[N],ans[N];
int visit[N],mark[N];
int Djudge(POINT a1, POINT a2, POINT a3)
{
int calculate = a1.x*a2.y + a3.x*a1.y + a2.x*a3.y - a3.x*a2.y - a2.x*a1.y - a1.x*a3.y;
return calculate;
}
bool cmpxy(const POINT a, const POINT b) //按x軸排序,如果x相同,按y軸排序
{
if (a.x != b.x)
return a.x < b.x;
else
return a.y < b.y;
}
void DealLeft(int first, int last)
{
int max = 0, index = -1;
int i = first;
if (first < last)
{
for (i = first+1; i < last; i++) //注意兩端,對於first和last,沒必要再進行計算
{
int calcu = Djudge(p[first], p[i], p[last]);
if (calcu == 0) { visit[i] = 1; } //
if (calcu > max)
{
max = calcu;
index = i;
}
}
}
else
{
for (i-1; i >last; i--) //如果first>last,重復上述過程,注意這里下界不是0.
{
int calcu = Djudge(p[first], p[i], p[last]);
if (calcu == 0) {visit[i] = 1;} //
if (calcu > max)
{
max = calcu;
index = i;
}
}
}
if (index != -1)
{
visit[index] = 1; //對取到的點進行標注
DealLeft(first, index);
DealLeft(index, last);//分治的部分
}
}
int main()
{
cout<<"請輸入點數:"<<endl;
cin >> n;
cout<<"請輸入點的坐標:"<<endl;
for (int i = 0; i < n; i++)
{
cin >> p[i].x >> p[i].y;
visit[i] = 0;
}
visit[0] = 1;
visit[n - 1] = 1;
sort(p, p + n, cmpxy);
DealLeft(0, n - 1); //查找上凸包;
DealLeft(n - 1, 0); //查找下凸包;
int t = 0;
for (int i = 0; i < n; i++)
{
if (visit[i] == 1)
{
ans[t].x = p[i].x;
ans[t].y = p[i].y;
t++;
}
}
//順時針輸出
mark[0] = mark[t - 1] = 1; //數組mark避免重復檢查降低效率
for (int i = 1; i < t - 1; i++)
{
mark[i] = 0;
}
cout<<"凸包點的坐標:"<<endl;
cout << ans[0].x << " " <<ans[0].y<< endl;
for (int i =1; i < t-1; i++)
{
int d = Djudge(ans[0], ans[t-1], ans[i]);
if (d >= 0)
{
cout << ans[i].x << " " << ans[i].y << endl;
mark[i] = 1;
}
}
cout << ans[t - 1].x << " " << ans[t - 1].y << endl;
for (int i = 1; i < t; i++)
{
if (mark[i] != 1)
{
int d = Djudge(ans[0], ans[t - 1], ans[i]);
if (d < 0)
{
cout << ans[i].x << " " << ans[i].y << endl;
}
}
}
return 0;
}
