【BZOJ】【1069】【SCOI2007】最大土地面积

计算几何/旋转卡壳



  从已知点中选出四个使得选出的四边形面积最大,很明显我们应该在凸包上搞。

  我一开始的思路是:枚举 i ,找到 i 的对锺点cur1,这两个点将凸包分成了两半,我们在左半中枚举一个 j ,然后在右半中找一个离 j 最远的“对锺点”(可能不是?反正找的是最远……)cur2,然后求cur1和cur2都是单调的,复杂度为枚举 i, j的$O(n^2)$

  然而跪了= =然后我去Orz了proverbs的题解,得到启示:我们可以枚举一条对角线,然后在左半和右半中各找一条跟这条对角线最远的点!这两个点的寻找明显是单调的,复杂度为枚举对角线的两个端点的$O(n^2)$

  Orzzzzz思路还是不够开阔啊

  一开始错我还以为是旋转卡壳写错了……后来发现原来是凸包写错了QAQ

 1 /**************************************************************
 2     Problem: 1069
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:284 ms
 7     Memory:1340 kb
 8 ****************************************************************/
 9
10 //BZOJ 1069
11 #include<cmath>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 typedef long long LL;
23 inline int getint(){
24     int r=1,v=0; char ch=getchar();
25     for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) r=-1;
26     for(; isdigit(ch);ch=getchar()) v=v*10-‘0‘+ch;
27     return r*v;
28 }
29 const int N=2010;
30 /*******************template********************/
31 struct Poi{
32     double x,y;
33     Poi(){}
34     Poi(double x,double y):x(x),y(y){}
35     void read(){scanf("%lf%lf",&x,&y);}
36 }p[N],ch[N];
37 typedef Poi Vec;
38 Vec operator - (const Poi &a,const Poi &b){return Vec(a.x-b.x,a.y-b.y);}
39 bool operator < (const Poi &a,const Poi &b){return a.x<b.x || (a.x==b.x && a.y<b.y);}
40 inline double Dot(const Poi &a,const Poi &b){return a.x*b.x+a.y*b.y;}
41 inline double Cross(const Poi &a,const Poi &b){return a.x*b.y-a.y*b.x;}
42
43 int n,m;
44 double ans;
45 void graham(Poi *p,int n){
46     sort(p+1,p+n+1);
47     ch[++m]=p[1];
48     F(i,2,n){
49         while(m>1 && Cross(ch[m]-ch[m-1],p[i]-ch[m-1])<=0) m--;
50         ch[++m]=p[i];
51     }
52     int k=m;
53     D(i,n-1,1){
54         while(m>k && Cross(ch[m]-ch[m-1],p[i]-ch[m-1])<=0) m--;
55         ch[++m]=p[i];
56     }
57     if (n>1) m--;
58 }
59 double getans(Poi a1,Poi a2,Poi b1,Poi b2){
60     return Cross(a2-a1,b1-a1)+Cross(b2-b1,a1-b1);
61 }
62 void rot(Poi *p,int n){
63     int cur1=2,cur2,j;
64     F(i,1,n) p[i+n]=p[i];
65     F(i,1,n-1){
66         cur1=i+1;
67         j=cur1+1;
68         cur2=j+1;
69         for(;j<i+n-1;j++){
70             while(Cross(p[cur1+1]-p[i],p[j]-p[i]) > Cross(p[cur1]-p[i],p[j]-p[i]))
71                 cur1=cur1%n+1;
72             while(Cross(p[cur2+1]-p[j],p[i]-p[j]) > Cross(p[cur2]-p[j],p[i]-p[j])){
73                 cur2=cur2%n+1;
74                 if (cur2>=i+n-1) break;
75             }
76             if (cur2>i+n-1) break;
77             ans=max(ans,getans(p[i],p[cur1],p[j],p[cur2]));
78         }
79     }
80 }
81 int main(){
82 #ifndef ONLINE_JUDGE
83     freopen("1069.in","r",stdin);
84 //  freopen("1069.out","w",stdout);
85 #endif
86     n=getint();
87     F(i,1,n) p[i].read();
88     graham(p,n);
89     rot(ch,m);
90     printf("%.3f\n",ans*0.5);
91     return 0;
92 }

1069: [SCOI2007]最大土地面积

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 1853  Solved: 683
[Submit][Status][Discuss]

Description

在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。

Input

第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。

Output

最大的多边形面积,答案精确到小数点后3位。

Sample Input

5
0 0
1 0
1 1
0 1
0.5 0.5

Sample Output

1.000

HINT

数据范围 n<=2000, |x|,|y|<=100000

Source

[Submit][Status][Discuss]

时间: 2024-10-10 02:54:24

【BZOJ】【1069】【SCOI2007】最大土地面积的相关文章

bzoj 1069 [SCOI2007]最大土地面积(旋转卡壳)

1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2277  Solved: 853[Submit][Status][Discuss] Description 在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. Input 第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标. Output 最大的多边形面积,答案精确到小

●BZOJ 1069 [SCOI2007]最大土地面积

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1069 题解: 计算几何,凸包,旋转卡壳 其实和这个题差不多,POJ 2079 Triangle 把四边形看出两个三角形就好了. 复杂度$O(N^2)$ 代码: #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #

bzoj 1069: [SCOI2007]最大土地面积

先求出凸包,旋转卡壳,可以枚举对角线,再分别找对角线两边最远的点... 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<queue> 7 #define M 100005 8 #define ll long long 9 using namespace std

BZOJ 1069 [SCOI2007]最大土地面积 旋转卡壳

题意:链接 方法:旋转卡壳 解析: 跟POJ2079那个三角形的很像. 所以思路其实也是一个思路. 但是注意到本题是找四边形,如果找三个动点的话好像不太现实. 所以我们枚举对角线的话,对角线上下肯定各有一个点,而且发现下面的点逆时针转动的时候,上面的点其实也是逆时针走. 所以按照旋转卡壳的思想,我们需要枚举一下对角线,再找两个动点更新最大即可. 这个复杂度是O(n^2)->枚举定点以及其对角点,对于本题来说可过. 代码: #include <cmath> #include <cst

1069: [SCOI2007]最大土地面积

1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 2961  Solved: 1162[Submit][Status][Discuss] Description 在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. Input 第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标. Output 最大的多边形面积,答案精确到

【BZOJ】1069: [SCOI2007]最大土地面积(凸包+旋转卡壳)

http://www.lydsy.com/JudgeOnline/problem.php?id=1069 显然这四个点在凸包上,然后枚举两个点找上下最大的三角形即可. 找三角形表示只想到三分QAQ....... 看了题解发现....这是单调的....直接扫...然后,这货叫“旋转卡壳”?是qia还是ka.... 自己一开始写的wa了........然后照标程写,,又wa了.... 后来发现是凸包写渣了QAQ...自己原来的找三角形是没问题的...我好sb..... 可是,为嘛凸包这样写会错. c

【BZOJ 1069】 [SCOI2007]最大土地面积

1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 1677  Solved: 588 [Submit][Status] Description 在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. Input 第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标. Output 最大的多边形面积,答案精确到小数点后3位.

BZOJ 1073: [SCOI2007]kshort

二次联通门 : BZOJ 1073: [SCOI2007]kshort /* BZOJ 1073: [SCOI2007]kshort A* k短路 但是会爆一个点, 是卡A*的 */ #include <cstdio> #include <iostream> #include <cstring> #include <queue> #include <vector> #include <algorithm> #include <c

BZOJ 1069 SCOI 2007 最大土地面积 凸包+旋转卡壳

题目大意:给出平面上的一些点,求其中四个点的最大四边形的面积. 思路:简单yy一下发现这些点肯定都在凸包上,先求个凸包.然后直接暴力肯定是不行的,我们需要一个O(n^2)的做法,比较简单的想法是枚举最后要求的四边形的一条对线,那么这个四边形就被分割成了两个三角形,剩下两个点与这条线组成的三角形的面积和就是答案. 按照旋转卡壳的思想不难发现,这两个点都是单调的.所以枚举对角线然后扫n圈就可以了. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cm

[BZOJ 1066] [SCOI2007] 蜥蜴 【最大流】

题目链接:BZOJ - 1066 题目分析 题目限制了高度为 x 的石柱最多可以有 x 只蜥蜴从上面跳起,那么就可以用网络流中的边的容量来限制.我们把每个石柱看作一个点,每个点拆成 i1, i2,从 i1 到 i2 连一条边,容量为这个石柱 i 的高度,即跳跃次数限制.来到这个石柱就是向 i1 连边,从这个石柱跳起就是从 i2 向外连边,这样只要从石柱 i 跳起就一定会消耗 i1 到 i2 的边的容量.如果 i 有蜥蜴,就从 S 到 i1 连一条容量为 1 的边,如果从石柱 i 能跳出边界,就从