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