题意

题目描述

给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点坐标

输入输出格式

输入格式:

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

输出格式:

第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点

输入输出样例

输入样例#1:
复制

  1. 6 1.0 3.00000
  2.  
  3. 1 4.00000
  4.  
  5. 2.0000 1
  6.  
  7. 3 0.0000
  8.  
  9. 3.00000 6
  10.  
  11. 6.0 3.0
输出样例#1:
复制

  1. 18.00000
  2.  
  3. 3.00000 0.00000
  4.  
  5. 6.00000 3.00000
  6.  
  7. 3.00000 6.00000
  8.  
  9. 0.00000 3.00000

说明

感谢 @intruder 提供题目简述

分析

参照wzq_QwQ的题解。

先求凸包,然后求最小矩形覆盖。

有一个显而易见的结论:选择的最小矩阵一定有一条边与凸包上的一条边重合。

我们可以枚举在矩阵上的这个边,然后再以这条边找到卡住的相对的最左边的点以及最右边的点,和相对的最上面的点。

画个图

假设我们枚举到了AB这条边。

然后目前的相对的最右边的点是点C,相对的最左边的点是点E,相对的最高点时点D。

先说怎么卡壳的吧。

首先对于最右边的点来说,卡(qia)的是点积最大,最左边的呢卡的是点积最小的,但是注意一个问题,第一次卡(qia)的时候这个最左边的一定是最高点的后面的点,这是很显然的,

不然我们如果遇到前面有点积相同的时候是卡不过去的。

所以第一次卡的时候要把最左边的点从最高点开始转。

最高点显然就是叉积最大嘛..

因为有叉积,我们可以求出来这个矩阵的宽的长度。

长怎么求呢?

利用点积。

我们知道AB的线段长,又知道向量AB与向量AE的点积,所以我们能求出来AE在AB方向上的投影。

于是就知道FA

同理右边可求。

然后现在我们求出来了矩阵长和宽,所以就能知道第一问面积了。

但是第二问怎么办呢?我们知道点A的坐标,考虑从向量AB的方向开始逆时针找矩阵的四个定点。其实就是把向量乘一下

AG我们都知道,所以就把AB乘成AG就知道G。

其余的同理。

时间复杂度\(O(n \log n)\)

代码

注意会输出-0这种情况。

  1. #include<algorithm>
  2. #include<cstdio>
  3. #include<cmath>
  4. #define co const
  5. using namespace std;
  6. co double eps=1e-8;
  7. typedef struct Point{double x,y;}Vector;
  8. bool operator<(co Point&u,co Point&v) {return u.x<v.x||u.x==v.x&&u.y<v.y;}
  9. Vector operator+(co Vector&u,co Vector&v) {return (Vector){u.x+v.x,u.y+v.y};}
  10. Vector operator-(co Vector&u,co Vector&v) {return (Vector){u.x-v.x,u.y-v.y};}
  11. double cross(co Vector&u,co Vector&v) {return u.x*v.y-u.y*v.x;}
  12. double dot(co Vector&u,co Vector&v) {return u.x*v.x+u.y*v.y;}
  13. double length(co Vector&u) {return sqrt(dot(u,u));}
  14. Vector operator*(co Vector&u,double k) {return (Vector){u.x*k,u.y*k};}
  15. co int N=5e4+1;
  16. int n,m;
  17. Point p[N],ch[N*2],print[4];
  18. double Rotating_Calipers(){
  19. double ans=1e18;
  20. int p=1,q=1,r=1;
  21. for(int i=0;i<m;++i){
  22. Vector u=ch[i+1]-ch[i];
  23. double lu=length(u);
  24. while(dot(u,ch[p+1]-ch[i])-dot(u,ch[p]-ch[i])>-eps) p=(p+1)%m;
  25. while(cross(u,ch[r+1]-ch[i])-cross(u,ch[r]-ch[i])>-eps) r=(r+1)%m;
  26. if(!i) q=r;
  27. while(dot(u,ch[q+1]-ch[i])-dot(u,ch[q]-ch[i])<eps) q=(q+1)%m;
  28. double R=dot(ch[p]-ch[i],u)/lu;
  29. double L=fabs(dot(ch[q]-ch[i],u)/lu);
  30. double leng=L+R;
  31. double heig=cross(u,ch[r]-ch[i])/lu;
  32. if(ans>leng*heig){
  33. ans=leng*heig;
  34. print[0]=ch[i]+u*(R/lu);
  35. print[1]=print[0]+(ch[p]-print[0])*(heig/length(ch[p]-print[0]));
  36. print[2]=print[1]+(ch[r]-print[1])*(leng/length(ch[r]-print[1]));
  37. print[3]=print[2]+(ch[q]-print[2])*(heig/length(ch[q]-print[2]));
  38. }
  39. }
  40. return ans;
  41. }
  42. int main(){
  43. scanf("%d",&n);
  44. for(int i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y);
  45. sort(p+1,p+n+1);
  46. for(int i=1;i<=n;++i){
  47. while(m>=2&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) --m;
  48. ch[m++]=p[i];
  49. }
  50. for(int k=m,i=n-1;i>=1;--i){
  51. while(m>=k+1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) --m;
  52. ch[m++]=p[i];
  53. }
  54. if(n>1) --m;
  55. printf("%.5lf\n",Rotating_Calipers());
  56. int pre=0;
  57. for(int i=1;i<=3;++i)
  58. if(print[i].y<print[pre].y||fabs(print[i].y-print[pre].y)<eps&&print[i].x<print[pre].x) pre=i;
  59. for(int i=0;i<4;++i) {
  60. if(fabs(print[(pre+i)%4].x)<eps) print[(pre+i)%4].x=0;
  61. if(fabs(print[(pre+i)%4].y)<eps) print[(pre+i)%4].y=0;
  62. printf("%.5lf %.5lf\n",print[(pre+i)%4].x,print[(pre+i)%4].y);
  63. }
  64. }

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

  1. 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖

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

  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. 【BZOJ1185】[HNOI2007]最小矩形覆盖(凸包,旋转卡壳)

    [BZOJ1185][HNOI2007]最小矩形覆盖(凸包,旋转卡壳) 题面 BZOJ 洛谷 题解 最小的矩形一定存在一条边在凸包上,那么枚举这条边,我们还差三个点,即距离当前边的最远点,以及做这条边 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. mySQL 分组查询,根据分组的字段,取最小值

    今天看到别人问的问题,给别人写了一条sql! CREATE TEMPORARY TABLE tmp_table ( id INTEGER not NULL, uname VARCHAR(10) NOT ...

  2. 字符与字符串3——char 的大小

    字符变量占用内存的大小,也就是char类型声明的变量,这个变量占多少字节. 一字节 char c = 'A'; printf("%d,%d\n", sizeof(c),sizeof ...

  3. pymongo 对mongoDB的操作

    #文档地址 http://api.mongodb.com/python/current/api/pymongo/collection.html collection级别的操作: find_and _m ...

  4. Git超实用总结

    Git 是什么? Git 是一个分布式的代码管理容器,本地和远端都保有一份相同的代码. Git 仓库主要是由是三部分组成:本地代码,缓存区,提交历史,这几乎是所有操作的本质,但是为了文章更加简单易懂, ...

  5. PODOFO编译

    由于LibHaru库只能创建PDF,所以只能换了. PODOFO项目的依赖项目有: FreeType2: https://sourceforge.net/projects/freetype/files ...

  6. 搭建Django项目

    命令行搭建Django项目 1.安装django 在指定解释器环境下安装django 1.11.9 在真实python3环境下: pip3 install django==1.11.9 在虚拟环境下: ...

  7. Mysql数据库文件迁移并修改默认数据文件存储位置

    环境: 1.两台Win10电脑 2.MySql5.6 过程: 1.原电脑停止MySql服务 2.复制C:\ProgramData\MySQL\MySQL Server 5.6\data文件夹到目标电脑 ...

  8. Day9作业及默写

    1,整理函数相关知识点,写博客. 2,写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者. def func(obj): return obj[1::2] 3, ...

  9. LeetCode--219、268、283、414、448 Array(Easy)

    219. Contains Duplicate II Given an array of integers and an integer k, find out whether there are t ...

  10. FZU 2273 Triangles 第八届福建省赛 (三角形面积交 有重边算相交)

    Problem Description This is a simple problem. Given two triangles A and B, you should determine they ...