题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=1185

题解:

计算几何,凸包,旋转卡壳

结论:矩形的某一条边在凸包的一条边所在的直线上。

(证不来,网上好像也没看到证明。。。诶。。。)

通过结论,问题转化为枚举凸包每条边,然后求出当矩形的一条边在该边所在的直线上时的最小矩形

即我们需要求出在凸包上,相对与这条边的最右边,最上面和最左边的点,

而最上面的点可以通过叉积得到最优位置,

最左和最右就可以通过点积的到最优位置,(一个点积最大,一个点积最小)。

同时由于随着边的顺时针枚举,这三个东西都具有单调性,所以用旋转卡壳。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50050
using namespace std;
const double eps=1e-10;
int sign(double x){
if(fabs(x)<=eps) return 0;
return x<0?-1:1;
}
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
void Read(){scanf("%lf%lf",&x,&y);}
};
typedef Point Vector;
bool operator < (Point A,Point B){return sign(A.x-B.x)<0||(sign(A.x-B.x)==0&&sign(A.y-B.y)<0);}
Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double k){return Vector(A.x*k,A.y*k);}
double operator ^ (Vector A,Vector B){return A.x*B.y-A.y*B.x;}
double operator * (Vector A,Vector B){return A.x*B.x+A.y*B.y;}
Point D[MAXN],C[MAXN],ANS[6],tmp[6];
int Andrew(int dnt){
int cnt=0,k;
sort(D+1,D+dnt+1);
for(int i=1;i<=dnt;i++){
while(cnt>1&&sign((C[cnt]-C[cnt-1])^(D[i]-C[cnt-1]))<=0) cnt--;
C[++cnt]=D[i];
} k=cnt;
for(int i=dnt-1;i>=1;i--){
while(cnt>k&&sign((C[cnt]-C[cnt-1])^(D[i]-C[cnt-1]))<=0) cnt--;
C[++cnt]=D[i];
}
return cnt-(dnt>1);
}
double TA(Point P1,Point P2,Point P){//Triangle_Area
return fabs((P-P1)^(P-P2))/2;
}
double PP(Point P1,Point P2,Point P){//Projection_Product
return (P-P1)*(P2-P1);
}
double GL(Vector A){//Get_Length
return sqrt(A*A);
}
Vector UV(Vector A){//Unit_Vector
double len=GL(A);
return Vector(A.x*(1/len),A.y*(1/len));
}
double DTL(Point P,Point P1,Point P2){//Distant_to_Line
return fabs(((P-P1)^(P-P2))/GL(P2-P1));
}
double rectangle(Vector v,Point d,Point r,Point u,Point l){
static Vector _v,w; static double t,h;
_v=Vector(-v.y,v.x);
v=UV(v); _v=UV(_v); w=l-d;
t=(w^_v)/(v^_v);
tmp[1]=d+(v*t);
h=DTL(r,tmp[1],tmp[1]+_v);
tmp[2]=tmp[1]+v*h;
h=DTL(u,tmp[1],tmp[1]+v);
tmp[4]=tmp[1]+_v*h;
tmp[3]=tmp[1]+((tmp[2]-tmp[1])+(tmp[4]-tmp[1]));
return TA(tmp[1],tmp[3],tmp[4])+TA(tmp[1],tmp[3],tmp[2]);
}
double RC(int cnt){//Rotating_Calipers
double S=1e300,_S; C[cnt+1]=C[1];
int l,r=1,u=1;
for(int i=1;i<=cnt;i++){
while(sign(PP(C[i],C[i+1],C[r])-PP(C[i],C[i+1],C[r+1]))<=0) r=r%cnt+1;
while(sign(TA(C[i],C[i+1],C[u])-TA(C[i],C[i+1],C[u+1]))<=0) u=u%cnt+1;
if(i==1) l=r;
while(sign(PP(C[i],C[i+1],C[l])-PP(C[i],C[i+1],C[l+1]))>0) l=l%cnt+1;
_S=rectangle(C[i+1]-C[i],C[i],C[r],C[u],C[l]);
if(sign(S-_S)>0){
S=_S;for(int k=1;k<=4;k++) ANS[k]=tmp[k];
}
}
return S;
}
void printPoint(){
int p=1; for(int i=2;i<=4;i++)
if(sign(ANS[i].y-ANS[p].y)<0||(sign(ANS[i].y-ANS[p].y==0)&&sign(ANS[i].x-ANS[p].x)<0)) p=i;
for(int i=1;i<=4;i++,p=p%4+1) printf("%lf %lf\n",ANS[p].x,ANS[p].y);
}
int main(){
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) D[i].Read();
printf("%.5lf\n",RC(Andrew(n)));
printPoint();
return 0;
}

  

●BZOJ 1185 [HNOI2007]最小矩形覆盖的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. BZOJ 1185 [HNOI2007]最小矩形覆盖 ——计算几何

    程序写的太垃圾,卡不过去. GG,甘拜下风. #include <map> #include <cmath> #include <queue> #include & ...

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

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

随机推荐

  1. alpha-咸鱼冲刺day1-紫仪

    总汇链接 一,合照 emmmmm.自然是没有的. 二,项目燃尽图 三,项目进展   登陆界面随意写了一下.(明天用来做测试的) 把学姐给我的模板改成了自家的个人主页界面,侧边栏啥的都弄出来了(快撒花花 ...

  2. 安装iis8

    -------------------- @echo off     echo 正在添加IIS8.0 功能,依据不同的网络速率,全程大约需要5分钟时间...     start /w pkgmgr / ...

  3. 敏捷冲刺每日报告——Day2

    1.情况简述 Alpha阶段第一次Scrum Meeting 敏捷开发起止时间 2017.10.26 00:00 -- 2017.10.27 00:00 讨论时间地点 2017.10.26晚9:30, ...

  4. 201621123040《Java程序设计》第2周学习总结

    1.本周学习总结 关键词:Java中的字符串与数组 c语言基本语法的迁移 相关总结:在一周的学习过程中,我自主学习Java的基本语法,前期的相关语法与c语言的基本语法相近,也算是做到了很好的回顾:在郑 ...

  5. cpp常用函数总结

    //sprintf sprintf(temp_str_result, "%lf", temp_double); result = temp_str_result; (*begin) ...

  6. Apache的配置httpd.conf文件配置

    (1) 基本配置: ServerRoot "/mnt/software/apache2" #你的apache软件安装的位置.其它指定的目录如果没有指定绝对路径,则目录是相对于该目录 ...

  7. C# Unity游戏开发——Excel中的数据是如何到游戏中的 (四)2018.4.3更新

    本帖是延续的:C# Unity游戏开发--Excel中的数据是如何到游戏中的 (三) 最近项目不算太忙,终于有时间更新博客了.关于数据处理这个主题前面的(一)(二)(三)基本上算是一个完整的静态数据处 ...

  8. datetimepicker.js 使用笔记

    1.官网地址 官网传送门 2.属性及使用示例 2.1调用 html: <input  type="text"  readonly class="date" ...

  9. 单点登录实现机制:桌面sso

    参考链接,感谢作者:https://zm10.sm-tc.cn/?src=l4uLj8XQ0IiIiNGckZ2TkJiM0ZyQktCZlo2Mi5uNmp6S0I/QysrJyszPztGXi5K ...

  10. Lintcode373 Partition Array by Odd and Even solution 题解

    [题目描述] Partition an integers array into odd number first and even number second. 分割一个整数数组,使得奇数在前偶数在后 ...