题目链接

BZOJ1185

题解

最小矩形一定有一条边在凸包上,枚举这条边,然后旋转卡壳维护另外三个端点即可

计算几何细节极多

  1. 维护另外三个端点尽量不在这条边上,意味着左端点尽量靠后,右端点尽量靠前,加上或减去一个\(eps\)来处理
  2. \(C++\)中\(printf\)输出\(0.00000\)会变成\(-0.00000\),需要特判
  3. 用叉积点乘判距离大小,正负方向不要搞错
  4. 求凸包记得排序
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#define eps 1e-9
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define cls(s,v) memset(s,v,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 50005,maxm = 100005;
const double INF = 1e15;
struct point{double x,y;}p[maxn],G[maxn],t[5];
inline bool operator <(const point& a,const point& b){
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
inline point operator +(const point& a,const point& b){
return (point){a.x + b.x,a.y + b.y};
}
inline point operator -(const point& a,const point& b){
return (point){a.x - b.x,a.y - b.y};
}
inline double operator *(const point& a,const point& b){
return a.x * b.x + a.y * b.y;
}
inline point operator *(const point& a,const double& b){
return (point){a.x * b,a.y * b};
}
inline double cross(const point& a,const point& b){
return a.x * b.y - a.y * b.x;
}
inline double dis(const point& a,const point& b){
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double ans = INF;
int n,st[maxn],top;
void graham(){
sort(p + 1,p + 1 + n);
for (int i = 1; i <= n; i++){
while (top > 1 && cross(p[st[top]] - p[st[top - 1]],p[i] - p[st[top]]) >= 0) top--;
st[++top] = i;
}
int tmp = top;
for (int i = n - 1; i; i--){
while (top > tmp && cross(p[st[top]] - p[st[top - 1]],p[i] - p[st[top]]) >= 0) top--;
st[++top] = i;
}
top--;
REP(i,top) G[i - 1] = p[st[i]];
G[top] = G[0];
}
void work(){
int d,l,r; d = l = r = 1;
double L,R,D,H;
for (int i = 0; i < top; i++){
D = dis(G[i],G[i + 1]);
while (cross(G[d + 1] - G[i],G[i + 1] - G[i]) + eps >= cross(G[d] - G[i],G[i + 1] - G[i])) d = (d + 1) % top;
while ((G[i + 1] - G[i]) * (G[l + 1] - G[i + 1]) + eps >= (G[i + 1] - G[i]) * (G[l] - G[i + 1])) l = (l + 1) % top;
if (i == 0) r = d;
while ((G[i] - G[i + 1]) * (G[r + 1] - G[i]) - eps > (G[i] - G[i + 1]) * (G[r] - G[i])) r = (r + 1) % top;
H = fabs(cross(G[d] - G[i],G[i + 1] - G[i]) / D);
L = fabs((G[i + 1] - G[i]) * (G[l] - G[i + 1]) / D);
R = fabs((G[i + 1] - G[i]) * (G[r] - G[i]) / D);
//printf("(%.0lf,%.0lf) (%.0lf,%.0lf) ",G[i].x,G[i].y,G[i + 1].x,G[i + 1].y);
//printf("(%.0lf,%.0lf) (%.0lf,%.0lf) (%.0lf,%.0lf)",G[l].x,G[l].y,G[d].x,G[d].y,G[r].x,G[r].y);
//printf("D = %lf H = %lf\n",L + R + D,H);
double S = (L + R + D) * H;
if (S < ans){
ans = S;
t[0] = G[i + 1] + (G[i + 1] - G[i]) * (L / D);
t[1] = G[i] + (G[i] - G[i + 1]) * (R / D);
t[2] = t[1] + (G[r] - t[1]) * (H / dis(G[r],t[1]));
t[3] = t[0] + (G[l] - t[0]) * (H / dis(G[l],t[0]));
}
}
}
int main(){
scanf("%d",&n);
REP(i,n) scanf("%lf%lf",&p[i].x,&p[i].y);
graham();
//for (int i = 0; i <= top; i++) printf("(%lf,%lf)\n",G[i].x,G[i].y);
work();
if (fabs(ans) < eps) puts("0.00000");
else printf("%.5lf\n",ans);
int pos = 0;
for (int i = 1; i < 4; i++)
if (t[i].y < t[pos].y) pos = i;
for (int i = pos,j = 0; j < 4; i = (i + 1) % 4,j++){
if (fabs(t[i].x) < eps) printf("0.00000 ");
else printf("%.5lf ",t[i].x);
if (fabs(t[i].y) < eps) printf("0.00000\n");
else printf("%.5lf\n",t[i].y);
}
return 0;
}

BZOJ1185 [HNOI2007]最小矩形覆盖 【旋转卡壳】的更多相关文章

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

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

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

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

  3. 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)

    题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...

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

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

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

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

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

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

  7. BZOJ1185[HNOI2007] 最小矩形覆盖(旋转卡壳)

    BZOJ1185[HNOI2007] 最小矩形覆盖 题面 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点的坐标 分析 首先可以先求凸包,因为覆盖了凸包上的顶点,凸 ...

  8. 2018.10.18 bzoj1185: [HNOI2007]最小矩形覆盖(旋转卡壳)

    传送门 不难看出最后的矩形一定有一条边与凸包某条边重合. 因此先求出凸包,然后旋转卡壳求出当前最小矩形面积更新答案. 代码: #include<bits/stdc++.h> #define ...

  9. BZOJ1185 HNOI2007 最小矩形覆盖 凸包、旋转卡壳

    传送门 首先,肯定只有凸包上的点会限制这个矩形,所以建立凸包. 然后可以知道,矩形上一定有一条边与凸包上的边重合,否则可以转一下使得它重合,答案会更小. 于是沿着凸包枚举这一条边,通过旋转卡壳找到离这 ...

随机推荐

  1. redis系列--深入哨兵集群

    一.前言 在之前的系列文章中介绍了redis的入门.持久化以及复制功能,如果不了解请移步至redis系列进行阅读,当然我也是抱着学习的知识分享,如果有什么问题欢迎指正,也欢迎大家转载.而本次将介绍哨兵 ...

  2. Exp4 恶意代码分析 20155223

    Exp4 恶意代码分析 20155223 使用原生命令schtasks监视系统运行 在系统盘目录下建立脚本文件netstatlog.bat,包含以下命令: date /t >> c:\ne ...

  3. [c#][福利]BTTool种子文件修改工具

    前言 不知道各位看官是否有过类似的经历.好不容易找到一个电影的种子文件,想用百度云的离线下载功能去下载文件,却被百度云无情提示“离线文件因含有违规内容被系统屏蔽无法下载”!假设有这么一个场景,比如最近 ...

  4. 11、可扩展MySQL+12、高可用

    11.1.扩展MySQL 静态分片:根据key取hash,然后取模: 动态分片:用一个表来维护key与分片id的关系: 11.2.负载均衡 12. 12.2导致宕机得原因: 35%环境+35%性能+2 ...

  5. 【转载】C++引用详解

    原文:http://www.cnblogs.com/gw811/archive/2012/10/20/2732687.html 引用的概念 引用:就是某一变量(目标)的一个别名,对引用的操作与对变量直 ...

  6. 校内模拟赛 Label

    题意: n个点m条边的无向图,有些点有权值,有些没有.边权都为正.给剩下的点标上数字,使得$\sum\limits_{(u,v)\in E}len(u,v) \times (w[u] - w[v]) ...

  7. 问题解决:IDEA右键选择new新文件的时候没有JSP文件选项解决

    参考: https://blog.csdn.net/tomorrow_fine/article/details/74090308 用上面的方法就可以解决了, 但是如果把web目录设置成了额外的,那id ...

  8. MVC的多页面后台管理系统

    MVC的多页面后台管理系统 同样功能的后台管理系统,也是可以使用 ASP.NET MVC .Web API 和JQuery 来制作. 所有的功能都与Angular js的单页面相同.应用层所有的方法都 ...

  9. ReactJS实用技巧(2):从新人大坑——表单组件来看State

    不太清楚有多少初学React的同学和博主当时一样,在看完React的生命周期.数据流之后觉得已经上手了,甩开文档啪啪啪的开始敲了起来.结果...居然被一个input标签给教做人了. 故事是这样的:首先 ...

  10. linux chroot 命令

    chroot,即 change root directory (更改 root 目录).在 linux 系统中,系统默认的目录结构都是以 /,即以根 (root) 开始的.而在使用 chroot 之后 ...