POJ - 2079:Triangle (旋轉卡殼,求最大三角形)

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.

Inputios

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 −10  4 <= xi, yi <= 10  4 for all i = 1 . . . n.

Outputc++

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 Inputgit

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

題意:在二維平面上面找三個點構成三角形,使得其面積最大。spa

思路1:枚舉三角形的一條邊,而後經過旋轉卡殼找最遠的點; 本身想的,並且AC了。code

 

#include<iostream> #include<cstdio> #include<cmath> #include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define RC rotating_calipers
using namespace std; const int maxn=100010; struct point{ double x,y; point(double x=0,double y=0):x(x),y(y){} bool operator < (const point &c) const { return x<c.x||(x==c.x&&y<c.y);} point operator - (const point &c) const { return point(x-c.x,y-c.y);} double operator * (const point &c) const { return x*c.y-y*c.x; } double operator | (const point &c) const { return (x-c.x)*(x-c.x)+(y-c.y)*(y-c.y); } }; double det(point A,point B){ return A.x*B.y-A.y*B.x;} double det(point O,point A,point B){ return det(A-O,B-O);} point a[maxn],ch[maxn]; void convexhull(int n,int &top) { sort(a+1,a+n+1); top=0; for(int i=1;i<=n;i++){ while(top>1&&det(ch[top-1],ch[top],a[i])<=0) top--; ch[++top]=a[i]; } int ttop=top; for(int i=n-1;i>=1;i--){ while(top>ttop&&det(ch[top-1],ch[top],a[i])<=0) top--; ch[++top]=a[i]; } } double rotating_calipers(point p[],int top) { top--; double ans=0; int now; rep(i,1,top-2){ int now=i+2; rep(j,i+1,top-1){ while(now<=top&&fabs(det(p[i],p[j],p[now]))<fabs(det(p[i],p[j],p[now+1]))){ now++;
 } ans=max(ans,fabs(det(p[i],p[j],p[now]))); } } return ans; } int main() { int N; while(~scanf("%d",&N)&&N!=-1){ for(int i=1;i<=N;i++) scanf("%lf%lf",&a[i].x,&a[i].y); int top; convexhull(N,top); double ans=RC(ch,top); printf("%.2f\n",0.5*ans); } return 0; }

 

思路2:枚舉三角形的一個點,而後經過旋轉卡殼找最遠的邊。別人的代碼,AC了,可是拿去作CF的時候WA36了。blog

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define RC rotating_calipers
using namespace std; const int maxn=100010; struct point{ double x,y; point(double x=0,double y=0):x(x),y(y){} bool operator < (const point &c) const { return x<c.x||(x==c.x&&y<c.y);} point operator - (const point &c) const { return point(x-c.x,y-c.y);} }; double det(point A,point B){ return A.x*B.y-A.y*B.x;} double det(point O,point A,point B){ return det(A-O,B-O);} point a[maxn],ch[maxn]; void convexhull(int n,int &top) { sort(a+1,a+n+1); top=0; for(int i=1;i<=n;i++){ while(top>1&&det(ch[top-1],ch[top],a[i])<=0) top--; ch[++top]=a[i]; } int ttop=top; for(int i=n-1;i>=1;i--){ while(top>ttop&&det(ch[top-1],ch[top],a[i])<=0) top--; ch[++top]=a[i]; } } double rotating_calipers(point p[],int top) { double ans=0; int now1=1,now2=2; rep(i,1,top){ while(fabs(det(p[i],p[now1],p[now2]))<fabs(det(p[i],p[now1],p[now2+1]))){ now2++;if(now2==top+1) now2=1; }//利用其是單峯函數
while(fabs(det(p[i],p[now1],p[now2]))<fabs(det(p[i],p[now1+1],p[now2]))){ now1++;if(now1==top+1) now1=1; } ans=max(ans,fabs(det(p[i],p[now1],p[now2]))); } return ans; } int main() { int N; while(~scanf("%d",&N)&&N!=-1){ for(int i=1;i<=N;i++) scanf("%lf%lf",&a[i].x,&a[i].y); int top; convexhull(N,top); double ans=RC(ch,top-1); printf("%.2f\n",0.5*ans); } return 0; }
相關文章
相關標籤/搜索