luogu4166 最大土地面积 (旋转卡壳)

本文介绍了一种解决凸包问题的高效算法——旋转卡壳法。该方法通过枚举对角线的一个端点,并使另一端点沿凸包转动,利用叉积找出最大与最小值,实现O(N^2)的时间复杂度。文章提供了详细的算法步骤及C++代码实现。

首先这样的点一定在凸包上

然后旋转卡壳就可以

具体来说,枚举对角线的一个端点,另一个端点在凸包上转,剩下两个点就是一个叉积最大一个最小,而这两个点也是跟着转的

所以是$O(N^2)$

 1 #include<bits/stdc++.h>
 2 #include<tr1/unordered_map>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 #define MP make_pair
 5 using namespace std;
 6 typedef long long ll;
 7 typedef unsigned long long ull;
 8 typedef pair<int,int> pa;
 9 const int maxn=2005;
10 
11 inline ll rd(){
12     ll x=0;char c=getchar();int neg=1;
13     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
14     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
15     return x*neg;
16 }
17 
18 struct Vec{
19     double x,y;
20     Vec(double a=0,double b=0){x=a,y=b;}
21 }p[maxn],stk[maxn];
22 inline Vec operator -(Vec a,Vec b){return Vec(a.x-b.x,a.y-b.y);}
23 inline double operator *(Vec a,Vec b){return a.x*b.y-a.y*b.x;}
24 int N,sh;
25 
26 inline bool cmp(Vec a,Vec b){
27     double x=a*b;
28     return x?x>0:fabs(a.x)<fabs(b.x);
29 }
30 
31 inline int ne(int x,int y=1){return x+y>sh?x+y-sh:x+y;}
32 
33 int main(){
34     //freopen("","r",stdin);
35     N=rd();
36     for(int i=1;i<=N;i++){
37         scanf("%lf%lf",&p[i].x,&p[i].y);
38         if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[1].y)) swap(p[i],p[1]);
39     }
40     for(int i=N;i;i--) p[i]=p[i]-p[1];
41     sort(p+1,p+N+1,cmp);
42     for(int i=1;i<=N;i++){
43         while(sh>1&&(stk[sh]-stk[sh-1])*(p[i]-stk[sh-1])<=0) sh--;
44         stk[++sh]=p[i]; 
45     }
46     double ans=0;
47     for(int i=1;i<=sh;i++){
48         int a=ne(i,1),b=ne(i,2);
49         for(int j=ne(i,2);ne(j)!=i;j=ne(j)){
50             while((stk[ne(a)]-stk[i])*(stk[j]-stk[i])>=(stk[a]-stk[i])*(stk[j]-stk[i])) a=ne(a);
51             while((stk[j]-stk[i])*(stk[ne(b)]-stk[i])>=(stk[j]-stk[i])*(stk[b]-stk[i])) b=ne(b);
52             ans=max(ans,((stk[a]-stk[i])*(stk[j]-stk[i])+(stk[j]-stk[i])*(stk[b]-stk[i]))/2);
53         }
54     }
55     printf("%.3lf\n",ans);
56     return 0;
57 }

 

转载于:https://www.cnblogs.com/Ressed/p/10476499.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值