swustoj凸包面积(分治法)

麦兜是个淘气的孩子。一天,他在玩钢笔的时候把墨水洒在了白色的墙上。再过一会,麦兜妈就要回来了,麦兜为了不让妈妈知道这件事情,就想用一个白色的凸多边形把墙上的墨点盖住。你能告诉麦兜最小需要面积多大的凸多边形才能把这些墨点盖住吗? 现在,给出了这些墨点的坐标,请帮助麦兜计算出覆盖这些墨点的最小凸多边形的面积。

输入

多组测试数据。第一行是一个整数T,表明一共有T组测试数据。
每组测试数据的第一行是一个正整数N(0< N < = 105),表明了墨点的数量。接下来的N行每行包含了两个整数Xi和Yi(0<=Xi,Yi<=2000),表示每个墨点的坐标。每行的坐标间可能包含多个空格。

输出

每行输出一组测试数据的结果,只需输出最小凸多边形的面积。面积是个实数,小数点后面保留一位即可,不需要多余的空格。

样例输入

2
4
0 0
1 0
0 1
1 1
2
0 0
0 1

样例输出

1.0
0.0

题解:分治法求解。

1,找出所有点中x值最小和最大的点就是凸包顶点。

2,以这两点为界将点划分为上包和下包。

3,求上包:每次找离直线最远的点,必是凸包顶点。下包一样求解。

3,递归求解上下包,顺便求面积。


#include<iostream>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<map>
#include<string>
#include<stdio.h>
#include<vector>
#include<stack>
using namespace std;
struct node {
	int x, y;
}s[105];
vector<node>ans;
vector<int>::iterator it;
double ansans;
//求点s3在点s1,s2所连直线的上边,如果满足返回true
bool isup(node s1, node s2, node s3) {
	swap(s1, s2);
	int juge = s1.x*s2.y + s3.x*s1.y + s2.x*s3.y - s3.x*s2.y - s2.x*s1.y - s1.x*s3.y;
	//点s3在点s1,s2z左侧
	if ( juge > 0) {
		return 1;
	}
	else if(juge <= 0) {
		return 0;
	}
}
//求两点直线距离
double getlinedis(node s1, node s2) {
	return sqrt(pow(s1.x - s2.x, 2) + pow(s1.y - s2.y, 2));
}
//求三点决定的三角形面积
double getdis(node s1, node s2, node s3) {
	double a = getlinedis(s1, s2);
	double b = getlinedis(s1, s3);
	double c = getlinedis(s2, s3);
	double p = (a + b + c) / 2;
	return sqrt(p * (p - a)*(p - b)*(p - c));
}
//isupdp为1代表求上包,否则下包
void getup(node s1, node s2, vector<node>up,bool isupdp) {
	node temp;
	double _max = 0;
	double maxs = 0;
	for (int i = 0;i < up.size();i++) {
		double dis = getdis(s1, s2, up[i]);
		bool tt = isup(s1, s2, up[i]);
		if (!isupdp) {
			tt = !tt;
		}
		if (tt) {
			if (dis > _max) {
				_max = dis;
				maxs = dis;
				temp = up[i];
			}
		}
		else {
			if(up[i].x)
			up.erase(up.begin()+i);
			if (i != 0) {
				i--;
			}
		}
	}
	ans.push_back(temp);
	ansans += maxs;
	if (up.size() > 1) {
		getup(s1, temp, up,isupdp);
		getup(temp, s2, up, isupdp);
	}
}

bool cmp(node a, node b) {
	return a.y < b.y;
}

int main()
{
	int t;
	cin >> t;

	while (t--) {
		vector<node>v;
		int n;
		cin >> n;
		int _minid, _maxid;
		_minid = 0;
		_maxid = 0;
		for (int i = 0;i < n;i++) {
			scanf("%d%d", &s[i].x, &s[i].y);
			v.push_back(s[i]);
			if (s[_maxid].x > s[i].x) {
				_maxid = i;
			}
			if (s[_minid].x < s[i].x) {
				_minid = i;
			}
		}
		vector<node>up, down;
		for (int i = 0;i < n;i++) {
			if (i != _minid && i != _maxid) {
				if (isup(s[_minid], s[_maxid], s[i])) {
					up.push_back(s[i]);
				}
				else {
					down.push_back(s[i]);
				}
			}
		}
		ans.push_back(s[_minid]);
		ans.push_back(s[_maxid]);
		getup(s[_minid], s[_maxid], up, 1);
		getup(s[_minid], s[_maxid], down, 0);
		sort(ans.begin(), ans.end(), cmp);
		printf("%.1lf\n", ansans);
		ansans = 0;
	}
	return 0;
}



猜你喜欢

转载自blog.csdn.net/swust_zeng_zhuo_k/article/details/79980454
今日推荐