POJ 2079(计算几何初步——凸包加旋转卡壳)

唉~~~~~这题实在是坑爹,数据范围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
  1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<queue>
5 #include<vector>
6 #include<map>
7 #include<set>
8 #include<cmath>
9 #include<complex>
10 #include<algorithm>
11 #define EPS 1e-10
12 #define largty(x,y) (x-EPS)>(y)
13 #define smalty(x,y) (x+EPS)<(y)
14 #define nlargty(x,y) (x-EPS)<(y)
15 #define nsmalty(x,y) (x+EPS)>(y)
16 #define equal(x,y) (nlargty(x,y) && (nsmalt(x,y)))
17 //#define x real()
18 //#define y imag()
19 #define max(a,b) (a)>(b)?(a):(b)
20 #define min(a,b) (a)<(b)?(a):(b)
21 #define MAXN 50004
22 using namespace std;
23 //typedef complex<double> point;
24 struct point {
25 double x, y;
26 point(){}
27 point(double _x, double _y):x(_x),y(_y){}
28 point(const point &temp)
29 {
30 x = temp.x;
31 y = temp.y;
32 }
33 }data[MAXN],convex[MAXN];
34 point start(0,0);
35
36 inline double cross(const point &p1, const point &p2, const point &q1, const point &q2)
37 {
38 return (q2.y - q1.y)*(p2.x - p1.x) - (q2.x - q1.x)*(p2.y - p1.y);
39 }
40
41 inline bool cmp1(const point &a, const point &b)
42 {
43 return a.y < b.y || (a.y == b.y && a.x < b.x);
44 }
45
46 inline bool cmp2(const point &a, const point &b)//逆时针排序
47 {
48 point origin;
49 origin = start;
50 return cross(origin,a,origin,b) > 0 || (cross(origin,a,origin,b) == 0 && fabs(a.x) < fabs(b.x));
51 }
52
53 inline void convex_hull(int &cnt, int n)
54 {
55 sort(data,data+n,cmp1);
56 start = data[0];
57 sort(data+1,data+n,cmp2);
58 convex[cnt++] = start;
59 convex[cnt++] = data[1];
60 for (int i(2); i<n; ++i) {
61 while (cnt >= 2 && cross(convex[cnt-2],convex[cnt-1],convex[cnt-1],data[i]) <= 0)--cnt;
62 convex[cnt++] = data[i];
63 }
64 }
65
66 inline double rotating_calipers(int n)
67 {
68 int j = 1,k = 0;
69 double area(0);
70 for (int i(0); i<n; ++i) {
71 j = (i + 1)%n;
72 k = (j + 1)%n;
73 while (fabs(cross(convex[i],convex[j],convex[i],convex[k])) <
74 fabs(cross(convex[i],convex[j],convex[i],convex[(k+1)%n]))) {
75 k = (k + 1)%n;
76 }
77 while (j != i && k != i) {
78 area = max(area,fabs(cross(convex[i],convex[j],convex[i],convex[k])));
79 while (fabs(cross(convex[i],convex[j],convex[i],convex[k])) <
80 fabs(cross(convex[i],convex[j],convex[i],convex[(k+1)%n]))) {
81 k = (k + 1)%n;
82 }
83 j = (j + 1)%n;
84 }
85 }
86 return area;
87 }
88
89 int main()
90 {
91 int n;
92 while (scanf("%d",&n) && n != -1) {
93 for (int i(0); i<n; ++i) {
94 scanf("%lf%lf",&data[i].x,&data[i].y);
95 }
96 if (n <= 2) {
97 cout<<"0.00"<<endl;
98 continue;
99 }
100 int cnt(0);
101 convex_hull(cnt,n);
102 if (cnt <= 2) {
103 cout<<"0.00"<<endl;
104 continue;
105 } else {
106 if (cnt == 3) {
107 printf("%.2lf\n",fabs(cross(convex[0],convex[1],convex[0],convex[2]))/2);
108 } else {
109 printf("%.2lf\n",rotating_calipers(cnt)/2);
110 }
111 }
112 }
113 return 0;
114 }



你可能感兴趣的:(poj)