poj 2079 Triangle(旋转卡壳)
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 7637 | Accepted: 2238 |
Description
Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices are from the given points.
Input
The input consists of several test cases. The first line of each test case contains an integer n, indicating the number of points on the plane. Each of the following n lines contains two integer xi and yi, indicating the ith points. The last line of the input is an integer −1, indicating the end of input, which should not be processed. You may assume that 1 <= n <= 50000 and −104 <= xi, yi <= 104 for all i = 1 . . . n.
Output
For each test case, print a line containing the maximum area, which contains two digits after the decimal point. You may assume that there is always an answer which is greater than zero.
Sample Input
3 3 4 2 6 2 7 5 2 6 3 9 2 0 8 0 6 5 -1
Sample Output
0.50 27.00
Source
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <iostream> 5 #include <math.h> 6 using namespace std; 7 #define eps 1e-8 8 9 struct Point 10 { 11 int x,y; 12 Point(int _x = 0, int _y = 0) 13 { 14 x = _x; 15 y = _y; 16 } 17 Point operator -(const Point &b)const 18 { 19 return Point(x - b.x, y - b.y); 20 } 21 int operator ^(const Point &b)const 22 { 23 return x*b.y - y*b.x; 24 } 25 int operator *(const Point &b)const 26 { 27 return x*b.x + y*b.y; 28 } 29 void input() 30 { 31 scanf("%d%d",&x,&y); 32 } 33 }; 34 int dist2(Point a,Point b)//距离的平方!!!attention!! 35 { 36 return (a-b)*(a-b); 37 } 38 39 40 int dcmp(double a) 41 { 42 if(fabs(a)<eps)return 0; 43 if(a>0)return 1; 44 else return -1; 45 } 46 47 const int MAXN = 50010; 48 Point list[MAXN]; 49 int Stack[MAXN],top; 50 bool _cmp(Point p1,Point p2) 51 { 52 int tmp = (p1-list[0])^(p2-list[0]); 53 if(tmp > 0)return true; 54 else if(tmp == 0 && dist2(p1,list[0]) <= dist2(p2,list[0])) 55 return true; 56 else return false; 57 } 58 59 void Graham(int n)//求凸包 60 { 61 Point p0; 62 int k = 0; 63 p0 = list[0]; 64 for(int i = 1;i < n;i++) 65 if(p0.y > list[i].y || (p0.y == list[i].y && p0.x > list[i].x)) 66 { 67 p0 = list[i]; 68 k = i; 69 } 70 swap(list[0],list[k]); 71 sort(list+1,list+n,_cmp); 72 if(n == 1) 73 { 74 top = 1; 75 Stack[0] = 0; 76 return; 77 } 78 if(n == 2) 79 { 80 top = 2; 81 Stack[0] = 0; 82 Stack[1] = 1; 83 return; 84 } 85 Stack[0] = 0; 86 Stack[1] = 1; 87 top = 2; 88 for(int i = 2;i < n;i++) 89 { 90 while(top > 1 && ((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0 ) 91 top--; 92 Stack[top++] = i; 93 } 94 } 95 96 double Area(Point *p,int n) 97 { 98 double area=0; 99 for(int i=0; i<n; i++){ 100 area+=(p[i]^p[(i+1)%n]); 101 } 102 return fabs((double)(area)/2); 103 } 104 105 double rotating_calipers(Point p[],int n) 106 { 107 double ans = 0; 108 Point v; 109 int cur = 1; 110 for(int i = 0;i < n;i++)//先转k再转j再转i!!! 111 { 112 v = p[i]-p[(i+1)%n]; 113 int k,j; 114 j=(i+1)%n; 115 k=(j+1)%n; 116 while(k!=i&&j!=i) 117 { 118 v = p[i]-p[j];//wa无数次!忘记了j也在转啊!!! 119 while(dcmp(v^(p[(k+1)%n]-p[k])) < 0) 120 { 121 k = (k+1)%n; 122 } 123 Point aa[4]; 124 aa[0]=p[i];aa[1]=p[j%n];aa[2]=p[k%n]; 125 double tmp=Area(aa,3); 126 ans=max(ans,tmp); 127 j=(j+1)%n; 128 } 129 Point aa[4]; 130 aa[0]=p[i];aa[1]=p[j%n];aa[2]=p[k%n]; 131 double tmp=Area(aa,3); 132 ans=max(ans,tmp); 133 } 134 return ans; 135 } 136 Point p[MAXN]; 137 138 int main() 139 { 140 int n; 141 while(scanf("%d",&n) == 1&&n!=-1) 142 { 143 for(int i = 0;i < n;i++) 144 list[i].input(); 145 Graham(n); 146 for(int i = 0;i < top;i++) 147 { 148 p[i] = list[Stack[i]]; 149 } 150 printf("%.2f\n",rotating_calipers(p,top)) ; 151 } 152 return 0; 153 }