(hdu step 7.1.6)最大三角形(凸包的应用——在n个点中找到3个点,它们所形成的三角形面积最大)

题目:

最大三角形

Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 121 Accepted Submission(s): 61
 
Problem Description
老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角形拥有的面积最大。
Eddy对这道题目百思不得其解,想不通用什么方法来解决,因此他找到了聪明的你,请你帮他解决这个题目。
 
Input
输入数据包含多组测试用例,每个测试用例的第一行包含一个整数n,表示一共有n个互不相同的点,接下来的n行每行包含2个整数xi,yi,表示平面上第i个点的x与y坐标。你可以认为:3 <= n <= 50000 而且 -10000 <= xi, yi <= 10000.
 
Output
对于每一组测试数据,请输出构成的最大的三角形的面积,结果保留两位小数。
每组输出占一行。
 
Sample Input
3
3 4
2 6
3 7
6
2 6
3 9
2 0
8 0
6 6
7 7
 
Sample Output
1.50
27.00
 
Author
Eddy
 
 
Recommend
lcy
 


题目分析:

             凸包的简单应用,在n个点中找到3个点,它们所形成的三角形面积最大。这道题一般来说有两种思路:

1)直接暴力。这肯定会TLE,因为n的数据范围都在50000左右了。

2)先求凸包。然后再在凸包上去找这三个点,这样的话,数据规模就要小很多了。事实证明,能形成最大三角形的

这三个点也一定在凸包上。


代码如下:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

/**
 * 求n个点中任意三个点所形成的三角形的最大面积。
 * 1)直接暴力。肯定会TLE。因为n都是50000多了。
 *
 * 2)所形成的最大三角形的三个点肯定在凸包上。在凸包上找这三个点
 * 将问题转化成:
 * 在凸包上求三个点所形成的三角形的面积最大..
 */

const double epsi = 1e-8;
const double pi = acos(-1.0);
const int maxn = 50001;


struct PPoint{//结构体尽量不要定义成Point这种,容易和C/C++本身中的变量同名
	double x;
	double y;

	PPoint(double _x = 0,double _y = 0):x(_x),y(_y){

	}

	PPoint operator - (const PPoint& op2) const{
		return PPoint(x - op2.x,y - op2.y);
	}

	double operator^(const PPoint &op2)const{
		return x*op2.y - y*op2.x;
	}
};


inline int sign(const double &x){
	if(x > epsi){
		return 1;
	}

	if(x < -epsi){
		return -1;
	}

	return 0;
}

inline double sqr(const double &x){
	return  x*x;
}


inline double mul(const PPoint& p0,const PPoint& p1,const PPoint& p2){
	return (p1 - p0)^(p2 - p0);
}


inline double dis2(const PPoint &p0,const PPoint &p1){
	return sqr(p0.x - p1.x) + sqr(p0.y - p1.y);
}

inline double dis(const PPoint& p0,const PPoint& p1){
	return sqrt(dis2(p0,p1));
}

int n;
PPoint p[maxn];
PPoint convex_hull_p0;


inline bool convex_hull_cmp(const PPoint& a,const PPoint& b){
	return sign(mul(convex_hull_p0,a,b)>0)|| (sign(mul(convex_hull_p0,a,b)) == 0 && dis2(convex_hull_p0,a) < dis2(convex_hull_p0,b));
}

int convex_hull(PPoint* a,int n,PPoint* b){
	int i;
	for(i = 1 ; i < n ; ++i){
		if(sign(a[i].x - a[0].x) < 0 || (sign(a[i].x - a[0].x) == 0 && sign(a[i].y - a[0].y) < 0)){
			swap(a[i],a[0]);
		}
	}

	convex_hull_p0 = a[0];//这两行代码不要顺序调换了..否则会WA
	sort(a,a+n,convex_hull_cmp);

	b[0] = a[0];
	b[1] = a[1];
	int newn = 2;
	for(i = 2 ; i < n ; ++i){
		while(newn > 1 && sign(mul(b[newn-1],b[newn-2],a[i])) >= 0){
			newn--;
		}

		b[newn++] = a[i];
	}

	return newn;
}


/**
 * 有一个三角形的三个点来计算这个三角形的面积
 */
double crossProd(PPoint A, PPoint B, PPoint C) {
    return (B.x-A.x)*(C.y-A.y) - (B.y-A.y)*(C.x-A.x);
}


int main(){
	while(scanf("%d",&n)!=EOF){
		int i;
		for(i = 0 ; i < n ; ++i){
			scanf("%lf %lf",&p[i].x,&p[i].y);
		}

		n = convex_hull(p,n,p);
		p[n] = p[0];

		double max_ans = -1;

		int j;
		int k;
		for(i = 0 ; i < n ; ++i){
			for(j = i+1 ; j < n ; ++j){
				for(k = j+1 ; k <= n ; ++k){
					double ans = fabs(crossProd(p[i],p[j],p[k]))/2;

					if(max_ans < ans){
						max_ans = ans;
					}
				}
			}
		}

		printf("%.2lf\n",max_ans);
	}

	return 0;
}





你可能感兴趣的:((hdu step 7.1.6)最大三角形(凸包的应用——在n个点中找到3个点,它们所形成的三角形面积最大))