bzoj1069-最大土地面积
题目
给定\(n\ (n\le 2000)\)个坐标,求四个坐标使得围起来的四边形面积最大。
分析
最暴力的想法是枚举四个点,然而肯定超时。接着不知道怎么想到中途相遇,然而一点关系都没有。这里用到了一个单调性:
如果在凸包上确定了一个点\(x\),令\(x\)逆时针方向的第一个点为\(y\),这时确定了一个点\(z\)使得\(S_{\triangle XYZ}最大,那么当\)y\(逆时针移动的时候,使得三角形面积最大的点\)z\(就会不动或逆时针移动。这个性质发展成为我们说的旋转卡壳。
这就是说,如果在凸包上确定了一个点,那么我们可以\)O(n)\(求出包含这个点的所有凸包上的四边形的最大面积。
所以我们可以枚举所有点,在\)O(n^2)$中求出答案。
代码
这里有几个地方需要注意到。
- 求凸包极角排序的时候,选择的基础点一定是最下面,最左边的,而不可以仅仅是最下面的,否则会出现\(0\)和\(-0\)这种情况。
- 在求凸包单调栈弹出的时候,要用小于等于号,否则如果有重点的情况就会出现问题。
- 在计算答案时,每次移动\(j\)的时候要记得更新\(s1\)和\(s2\)。
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=2e3+10;
struct node {
double x,y;
} a[maxn],sta[maxn];
int top=0;
double P(double x) {
return x*x;
}
double dis(node a,node b) {
return sqrt(P(a.x-b.x)+P(a.y-b.y));
}
double cross(node a,node b,node c) {
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
bool cmp(node e,node f) {
double tmp=cross(a[1],e,f);
if (tmp>0) return true;
if (tmp<0) return false;
return dis(a[1],e)<dis(a[1],f);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("my.out","w",stdout);
#endif
int n;
scanf("%d",&n);
for (int i=1;i<=n;++i) {
scanf("%lf%lf",&a[i].x,&a[i].y);
if (a[i].y<a[1].y || (a[i].y==a[1].y && a[i].x<a[1].x)) swap(a[1],a[i]); // here
}
sort(a+2,a+n+1,cmp);
sta[top=1]=a[1];
for (int i=2;i<=n;++i) {
while (top>1 && cross(sta[top-1],sta[top],a[i])<=0) --top; // here
sta[++top]=a[i];
}
if (top<=4) {
double ans=0;
if (top>2) ans=cross(sta[1],sta[2],sta[3]);
if (top==4) ans+=cross(sta[1],sta[3],sta[4]);
ans/=2;
printf("%.3lf\n",ans);
return 0;
}
double ans=0;
for (int i=1;i<=top-2;++i) {
int j=(i+1)%top+1,k=i%top+1,l,id=j%top+1;
double s1=cross(sta[i],sta[k],sta[j])/2;
double s2=0;
for (l=id;l!=i;l=l%top+1) {
double tmp=cross(sta[i],sta[j],sta[l])/2;
if (tmp>s2) s2=tmp,id=l;
}
l=id;
ans=max(ans,s1+s2);
for (j=j%top+1;j%top+1!=i;j=j%top+1) {
s1=cross(sta[i],sta[k],sta[j])/2; // here
s2=cross(sta[i],sta[j],sta[l])/2; // here
if (l==j) l=l%top+1,s2=cross(sta[i],sta[j],sta[l])/2;
while (k%top+1!=j && cross(sta[i],sta[k%top+1],sta[j])/2>s1) k=k%top+1,s1=cross(sta[i],sta[k],sta[j])/2;
while (l%top+1!=i && cross(sta[i],sta[j],sta[l%top+1])/2>s2) l=l%top+1,s2=cross(sta[i],sta[j],sta[l])/2;
ans=max(ans,s1+s2);
}
}
printf("%.3lf\n",ans);
}
bzoj1069-最大土地面积的更多相关文章
- 【BZOJ-1069】最大土地面积 计算几何 + 凸包 + 旋转卡壳
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 2707 Solved: 1053[Submit][Sta ...
- bzoj1069 SCOI2007 最大土地面积
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 2560 Solved: 983 Description ...
- bzoj1069 [SCOI2007]最大土地面积 旋转卡壳
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 3767 Solved: 1501[Submit][Sta ...
- BZOJ1069 SCOI2007最大土地面积(凸包+旋转卡壳)
求出凸包,显然四个点在凸包上.考虑枚举某点,再移动另一点作为对角线,容易发现剩下两点的最优位置是单调的.过程类似旋转卡壳. #include<iostream> #include<c ...
- BZOJ1069 [SCOI2007]最大土地面积 【凸包 + 旋转卡壳】
题目链接 BZOJ1069 题解 首先四个点一定在凸包上 我们枚举对角线,剩下两个点分别是两侧最远的点 可以三分,复杂度\(O(n^2logn)\) 可以借鉴旋转卡壳的思想,那两个点随着对角线的一定单 ...
- [BZOJ1069][SCOI2007]最大土地面积(水平扫描法求凸包+旋转卡壳)
题意:在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成. 的多边形面积最大.n<=2000. 先求凸包,再枚举对角线,随着对角线的斜率上升,另外两 ...
- [BZOJ1069][SCOI2007]最大土地面积 凸包+旋转卡壳
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 3669 Solved: 1451[Submit][Sta ...
- [Bzoj1069][Scoi2007]最大土地面积(凸包)(旋转卡壳)
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 3629 Solved: 1432[Submit][Sta ...
- BZOJ1069 SCOI2007 最大土地面积 凸包、旋转卡壳
传送门 在这里假设可以选择两个相同的点吧-- 那么选出来的四个点一定会在凸包上 建立凸包,然后枚举这个四边形的对角线.策略是先枚举对角线上的一个点,然后沿着凸包枚举另一个点.在枚举另一个点的过程中可以 ...
- 【bzoj1069】最大土地面积
Description 在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. Input 第1行一个正整数N,接下来N行,每行2个数x,y ...
随机推荐
- .Net 面试题 汇总(六)
一.填空题 1.面向对象的语言具有(继承)性.(多态)性.(封装)性. 2.能用foreach遍历访问的对象需要实现 (IEnumberable)接口或声明(GetEnumberator)方法的类型. ...
- elk6.3.2在线安装中文分词工具IK
1.进入ES目录并执行安装(注意版本号改成你需要的版本) cd /usr/share/elasticsearch ./bin/elasticsearch-plugin install https:// ...
- Mybatis之关联查询及动态SQL
前言 实际开发项目中,很少是针对单表操作,基本都会联查多表进行操作,尤其是出一些报表的内容.此时,就可以使用Mybatis的关联查询还有动态SQL.前几篇文章已经介绍过了怎么调用及相关内容,因此这里只 ...
- WebService-CXF使用
一.SOAP和WSDL概念: SOAP(Simple Object Access Protocol):简单对象访问协议 SOAP作为一个基于XML语言的协议用于在网上传输数据 SOAP=在Http的基 ...
- php 用continue加数字实现foreach 嵌套循环中止
foreach($array as $key => $value) { if($value == 5)break; } // 这是一种. // 如果是嵌套的循环,用continue加数字也可以实 ...
- [CodeForce455A]Boredom
题面描述 Alex doesn't like boredom. That's why whenever he gets bored, he comes up with games. One long ...
- java基础-Comparator接口与Collections实现排序算法
java 排序Comparable和Comparator使用 java提供了两个排序用的接口Comparable和Comparator,一般情况下使用区别如下: Comparable 接口用于类的固定 ...
- 在页面使用echarts的地图(解决地图不完整)
测试环境:IDEA+Tomcat7 谷歌浏览器 创建好web工程,编写jsp页面,在自己编写的JSP页面上导包 现在echarts停止了在其网站上下载地图脚本,直接通过src引用网站上的china.j ...
- #pragma pack(n)对齐格式
#pragma pack(n)对齐格式 #pragma pack(n) 是预处理器用来指定对齐格式的指令,表示n对齐.当元素字节小于n时,要扩展到n:若元素字节大于n则占用其实际大小. struct ...
- 你真的了解JAVA里的String么
Java中String类细节问题 (考察点Java内存分配问题) 1. String str1 = "abc"; System.out.println(str1 == &quo ...