POJ 2079(计算几何初步——凸包加旋转卡壳)
2012-03-03 14:58
543 查看
唉~~~~~这题实在是坑爹,数据范围1<=N<=50000,很明显O(N^2)的算法过不了,但是居然过了-_-!!!!!!!!!!!!
跪求神牛高效算法。。。
先来分析下这题,给出N个点,从中选出3个点,使其面积达到最大。
先用凸包进行初步优化:因为最大面积三角形的顶点一定在凸包上。
然后直接在凸包上暴力枚举是肯定不行的。。O(N^3)
所以这要用到一种思想,旋转卡壳。
能够将其中一个点的枚举次数平摊为O(1).
所以总的时间复杂度为O(N^2).
旋转卡壳枚举思路:
先固定i,j这2个邻接的顶点。然后找出triangle_area(i,j,k)最大的那个K点。
然后再固定i,枚举j点,由于k点是随着j点的变化在变化,所以K点不必从开头重新枚举。
View Code
跪求神牛高效算法。。。
先来分析下这题,给出N个点,从中选出3个点,使其面积达到最大。
先用凸包进行初步优化:因为最大面积三角形的顶点一定在凸包上。
然后直接在凸包上暴力枚举是肯定不行的。。O(N^3)
所以这要用到一种思想,旋转卡壳。
能够将其中一个点的枚举次数平摊为O(1).
所以总的时间复杂度为O(N^2).
旋转卡壳枚举思路:
先固定i,j这2个邻接的顶点。然后找出triangle_area(i,j,k)最大的那个K点。
然后再固定i,枚举j点,由于k点是随着j点的变化在变化,所以K点不必从开头重新枚举。
View Code
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<map> #include<set> #include<cmath> #include<complex> #include<algorithm> #define EPS 1e-10 #define largty(x,y) (x-EPS)>(y) #define smalty(x,y) (x+EPS)<(y) #define nlargty(x,y) (x-EPS)<(y) #define nsmalty(x,y) (x+EPS)>(y) #define equal(x,y) (nlargty(x,y) && (nsmalt(x,y))) //#define x real() //#define y imag() #define max(a,b) (a)>(b)?(a):(b) #define min(a,b) (a)<(b)?(a):(b) #define MAXN 50004 using namespace std; //typedef complex<double> point; struct point { double x, y; point(){} point(double _x, double _y):x(_x),y(_y){} point(const point &temp) { x = temp.x; y = temp.y; } }data[MAXN],convex[MAXN]; point start(0,0); inline double cross(const point &p1, const point &p2, const point &q1, const point &q2) { return (q2.y - q1.y)*(p2.x - p1.x) - (q2.x - q1.x)*(p2.y - p1.y); } inline bool cmp1(const point &a, const point &b) { return a.y < b.y || (a.y == b.y && a.x < b.x); } inline bool cmp2(const point &a, const point &b)//逆时针排序 { point origin; origin = start; return cross(origin,a,origin,b) > 0 || (cross(origin,a,origin,b) == 0 && fabs(a.x) < fabs(b.x)); } inline void convex_hull(int &cnt, int n) { sort(data,data+n,cmp1); start = data[0]; sort(data+1,data+n,cmp2); convex[cnt++] = start; convex[cnt++] = data[1]; for (int i(2); i<n; ++i) { while (cnt >= 2 && cross(convex[cnt-2],convex[cnt-1],convex[cnt-1],data[i]) <= 0)--cnt; convex[cnt++] = data[i]; } } inline double rotating_calipers(int n) { int j = 1,k = 0; double area(0); for (int i(0); i<n; ++i) { j = (i + 1)%n; k = (j + 1)%n; while (fabs(cross(convex[i],convex[j],convex[i],convex[k])) < fabs(cross(convex[i],convex[j],convex[i],convex[(k+1)%n]))) { k = (k + 1)%n; } while (j != i && k != i) { area = max(area,fabs(cross(convex[i],convex[j],convex[i],convex[k]))); while (fabs(cross(convex[i],convex[j],convex[i],convex[k])) < fabs(cross(convex[i],convex[j],convex[i],convex[(k+1)%n]))) { k = (k + 1)%n; } j = (j + 1)%n; } } return area; } int main() { int n; while (scanf("%d",&n) && n != -1) { for (int i(0); i<n; ++i) { scanf("%lf%lf",&data[i].x,&data[i].y); } if (n <= 2) { cout<<"0.00"<<endl; continue; } int cnt(0); convex_hull(cnt,n); if (cnt <= 2) { cout<<"0.00"<<endl; continue; } else { if (cnt == 3) { printf("%.2lf\n",fabs(cross(convex[0],convex[1],convex[0],convex[2]))/2); } else { printf("%.2lf\n",rotating_calipers(cnt)/2); } } } return 0; }
相关文章推荐
- [Poj 2187]计算几何之凸包(三) {旋转卡壳初步}
- 计算几何之凸包(三) {旋转卡壳初步}
- 【计算几何】 Andrew凸包算法 + 旋转卡壳(以求点对最长距离为例) -- 以 POJ 2187 Beauty Contest 为例
- 【BZOJ1185】最小矩形覆盖 计算几何 凸包 旋转卡壳
- poj 2079(旋转卡壳求解凸包内最大三角形面积)
- HDU 5251 矩形面积 (计算几何+旋转卡壳求覆盖凸包的最小矩形面积)
- poj 2079 Triangle 凸包+旋转卡壳 求最大三角形面积
- 计算几何初步之凸包(POJ 1113、2007、1873、1228、3348)
- poj 2079 Triangle 凸包+旋转卡壳
- POJ 1113(计算几何初步——凸包加圆周长)
- POJ 2079 Triangle (凸包+旋转卡壳)
- poj 2079 Triangle (二维凸包旋转卡壳)
- POJ 2079 求最大三角形面积 (凸包+旋转卡壳)
- poj 2079 Triangle (二维凸包旋转卡壳)
- POJ 2187(计算几何+旋转卡壳法或暴力)
- POJ 2187 Beauty Contest [旋转卡壳]【计算几何】
- POJ 2079 Triangle(凸包+旋转卡壳求最大三角形面积)
- POJ 1873(计算几何初步——位运算枚举,求凸包)
- POJ 2079 Triangle 凸包+旋转卡壳
- POJ 2079 Triangle(凸包+旋转卡壳,求最大三角形面积)