题目链接:

洛谷 P3187 [HNOI2007]最小矩形覆盖

BZOJ 1185: [HNOI2007]最小矩形覆盖

Description

给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,

输出所求矩形的面积和四个顶点坐标

Input

第一行为一个整数n(3<=n<=50000)

从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法

Output

第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),

接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,

其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点

Sample Input

6 1.0 3.00000

1 4.00000

2.0000 1

3 0.0000

3.00000 6

6.0 3.0

Sample Output

18.00000

3.00000 0.00000

6.00000 3.00000

3.00000 6.00000

0.00000 3.00000

Solution

旋转卡壳

旋转卡壳求最小面积多边形外接矩形的模板题。

精度问题卡了好久,-0.00000 被卡了,真的毒瘤。

首先求凸包,然后用旋转卡壳维护最左边的点,最上面的点和最右边的点即可。(下图中的 \(L\), \(K\), \(J\) 点)

最上面的点的求法类似凸包的直径,就是求对踵点,用叉积维护即可。

最左边和最右边的点就是投影最大的点。用点积维护。

注:比较的时候最好不要直接用比较运算符。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-8;
const int maxn = 100000 + 5; int n; inline int dcmp(double x) {
if(fabs(x) < eps) return 0;
return x > 0? 1: -1;
} class Point {
public:
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) {}
Point operator+(Point a) {
return Point(a.x + x, a.y + y);
}
Point operator-(Point a) {
return Point(x - a.x, y - a.y);
}
bool operator<(const Point &a) const {
if (x == a.x)
return y < a.y;
return x < a.x;
}
Point operator*(double a) {
return Point(x * a, y * a);
}
bool operator==(const Point &a) const {
if (x == a.x && y == a.y)
return 1;
return 0;
}
double len() {
return sqrt(x * x + y * y);
}
double dis2(const Point a) {
return pow(x - a.x, 2) + pow(y - a.y, 2);
}
double dis(const Point a) {
return sqrt(dis2(a));
}
}; Point ans[10]; typedef Point Vector; double cross(Vector a, Vector b) {
return a.x * b.y - a.y * b.x;
} double dot(Vector a, Vector b) {
return a.x * b.x + a.y * b.y;
} typedef vector<Point> Polygon;
Polygon Andrew(Polygon P) {
int n = P.size(), k = 0;
vector<Point> H(2 * n);
sort(P.begin(), P.end());
for (int i = 0; i < n; ++i) {
while (k >= 2 && cross(H[k - 1] - H[k - 2], P[i] - H[k - 2]) < eps) {
k--;
}
H[k++] = P[i];
}
int t = k + 1;
for (int i = n - 1; i > 0; --i) {
while (k >= t && cross(H[k - 1] - H[k - 2], P[i - 1] - H[k - 2]) < eps) {
k--;
}
H[k++] = P[i - 1];
}
H.resize(k - 1);
return H;
} double rotating_caliper(Polygon v) {
double min_s = 1e18;
int cnt = v.size();
v.push_back(v[0]);
int u = 1, r = 1, l = 1;
for (int i = 0; i < cnt; ++i) {
// 最上面的点
while (dcmp(fabs(cross(v[u] - v[i], v[i + 1] - v[i])) - fabs(cross(v[u + 1] - v[i], v[i + 1] - v[i]))) <= 0) {
u = (u + 1) % cnt;
} // 最右边的点
while (dcmp(dot(v[r] - v[i], v[i + 1] - v[i]) - dot(v[r + 1] - v[i], v[i + 1] - v[i])) <= 0) {
r = (r + 1) % cnt;
} if(!i) l = r; // 最左边的点
while (dcmp(dot(v[l] - v[i], v[i + 1] - v[i]) - dot(v[l + 1] - v[i], v[i + 1] - v[i])) >= 0) {
l = (l + 1) % cnt;
}
double d = v[i].dis(v[i + 1]);
double R = dot(v[r] - v[i], v[i + 1] - v[i]) / d;
double L = dot(v[l] - v[i], v[i + 1] - v[i]) / d;
double ll = R - L;
double dd = fabs(cross(v[u] - v[i], v[i + 1] - v[i])) / d;
double s = ll * dd;
if(s < min_s) {
min_s = s;
ans[0] = v[i] + (v[i + 1] - v[i]) * (R / d);
ans[1] = ans[0] + (v[r] - ans[0]) * (dd / v[r].dis(ans[0]));
ans[2] = ans[1] + (v[i] - ans[0]) * (ll / R);
ans[3] = ans[2] + (ans[0] - ans[1]);
}
}
return min_s;
} int main() {
scanf("%d", &n);
Polygon s;
for(int i = 0; i < n; ++i) {
Point p;
scanf("%lf%lf", &p.x, &p.y);
s.push_back(p);
}
Polygon p = Andrew(s);
double d = rotating_caliper(p);
printf("%.5lf\n", d);
double miny = 1e18;
int index = 1;
for(int i = 0; i < 4; ++i) {
if(dcmp(ans[i].x) == 0) ans[i].x = 0;
if(dcmp(ans[i].y) == 0) ans[i].y = 0;
if(ans[i].y < miny) {
miny = ans[i].y;
index = i;
}
}
double minx = 1e18;
for(int i = 0; i < 4; ++i) {
if(ans[i].y == miny && ans[i].x < minx) {
minx = ans[i].x;
index = i;
}
}
for(int i = 0; i < 4; ++i) {
printf("%.5lf %.5lf\n", ans[(i + index) % 4].x, ans[(i + index) % 4].y);
}
return 0;
}

洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)的更多相关文章

  1. BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]

    1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1435  Solve ...

  2. bzoj 1185 [HNOI2007]最小矩形覆盖——旋转卡壳

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 矩形一定贴着凸包的一条边.不过只是感觉这样. 枚举一条边,对面的点就是正常的旋转卡壳. ...

  3. BZOJ 1185: [HNOI2007]最小矩形覆盖-旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标-备忘板子

    来源:旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标 BZOJ又崩了,直接贴一下人家的代码. 代码: #include"stdio.h" #include"str ...

  4. BZOJ:1185: [HNOI2007]最小矩形覆盖

    1185: [HNOI2007]最小矩形覆盖 这计算几何……果然很烦…… 发现自己不会旋转卡壳,补了下,然后发现求凸包也不会…… 凸包:找一个最左下的点,其他点按照与它连边的夹角排序,然后维护一个栈用 ...

  5. bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包

    [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 2081  Solved: 920 ...

  6. bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳

    题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...

  7. ●BZOJ 1185 [HNOI2007]最小矩形覆盖

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1185 题解: 计算几何,凸包,旋转卡壳 结论:矩形的某一条边在凸包的一条边所在的直线上. ( ...

  8. BZOJ 1185 [HNOI2007]最小矩形覆盖:凸包 + 旋转卡壳

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1185 题意: 给出二维平面上的n个点,问你将所有点覆盖的最小矩形面积. 题解: 先找出凸 ...

  9. 【bzoj1185】[HNOI2007]最小矩形覆盖 (旋转卡壳)

    给你一些点,让你用最小的矩形覆盖这些点 首先有一个结论,矩形的一条边一定在凸包上!!! 枚举凸包上的边 用旋转卡壳在凸包上找矩形另外三点... 注意精度问题 #include<cstdio> ...

随机推荐

  1. 建站手册-浏览器信息:Internet Explorer 浏览器

    ylbtech-建站手册-浏览器信息:Internet Explorer 浏览器 1.返回顶部 1. http://www.w3school.com.cn/browsers/browsers_inte ...

  2. ios打包,通过Xcode生成ipa文件

    ios打包,通过Xcode生成ipa文件 干货文章 ·2018-03-21 19:03:47 打开ios项目目录,配置证书 将运行设备选择,如下图 选择:Product -> Scheme -& ...

  3. nginx + gunicorn + django 2.0 踩坑

    部署踩坑 部署踩坑提前准备服务器端准备安装nginx使用uwsgi部署使用gunicorn配置配置nginx配置django中的路径url 提前准备 在本地能够 python(3) manage.py ...

  4. 聊聊动态链接和dl_runtime_resolve

    写在前面 linux下的动态链接相关结构,重新回顾_dl_runtime_resolve的流程以及利用方法 动态链接相关结构 为了高效率的利用内存,多个进程可以共享代码段.程序模块化方便更新维护等,动 ...

  5. ubuntu14.04 配置android studio环境

    二.复制所需的文件到ubuntu 2.1.如果你还没有linux版本的android studio.sdk.jdk请先下载所需文件,我已经上传到百度网盘了 下载地址: android studio-l ...

  6. hbase报错: hbase.PleaseHoldException: Master is initializing

    查看hbase服务状态报错:   hbase(main)::> status ERROR: org.apache.hadoop.hbase.PleaseHoldException: Master ...

  7. .NET WEB API 简单搭建

    首先是注释问题: 找到 跟目录下Areas/HelpPage/App_Start/HelpPageConfig.cs 加上代码就OK 了 还有在解决方案属性 点击生成  将XML文档文件勾上 API ...

  8. Linux上安装JDk教程

    使用如下命令 uname –a.如果输出结果中含有X86_64,表明系统是64位的,如果出现i686,证明系统是32位的. 没有安装包,就去官网下载 http://www.oracle.com/tec ...

  9. windows下注册ocx控件

    OCX 是对象类别扩充组件(Object Linking and Embedding (OLE) Control Extension):是可执行的文件的一种,但不可直接被执行: 是 ocx 控件的扩展 ...

  10. JavaWeb开发之二《JSP + Tomcat的第一个程序“Hello World”》

    搬以前写的博客[2014-12-10 22:41] 前一篇博客讲了Tomcat环境搭建,于是开始第一个“Hello JSP”程序. 服务器环境搭建好之后,我们开始写自己的网站,这里简单的写一个没有后台 ...