题意:给你一些点,找出两个可以包含所有点的矩形,一个保证矩形面积最小,一个保证矩形周长最小,输出两个最小值

题解:首先根据所有点求一个凸包,再在这个凸包上枚举每条边,作为矩形的一条边(这样可以保证最小)

   接着根据旋转卡壳的思想求出另外三条边,这样枚举判断就好

   求另三条边时首先方向是确定了的,找点就是旋转卡壳,思想就是:枚举的任意两条边a与b,a的另三条边与b的另三条边都不会再a与b之间,并且b对应边一定最a对应边的        后面(注意是循环的边)那么就是说,我们可以使用类似双指针方式维护,但是时间复杂度却为O(n)

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const ll INF=1LL<<60;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=500010;
struct Point
{double x,y;Point(double x=0,double y=0):x(x),y(y) {};inline Point operator-(const Point& a)const{return Point(x-a.x,y-a.y);}inline bool operator<(const Point& a)const{return sgn(x-a.x)<0||zero(x-a.x)&&sgn(y-a.y)<0;}inline Point operator+(const Point& a)const{return Point(x+a.x,y+a.y);}inline bool operator!=(const Point& a)const{return !(zero(x-a.x)&&zero(y-a.y));}
};
typedef Point Vector;
struct Line
{Point p;Vector v;double ang;//极角
    Line() {};Line(Point p,Vector v):p(p),v(v){ang=atan2(v.y,v.x);}inline bool operator<(const Line& L)const{return ang<L.ang;}
};
double Dis(Point A,Point B)
{return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
double Cross(Vector A,Vector B)
{return A.x*B.y-A.y*B.x;
}
int ConvexHull(Point *p,int n,Point *convex)//求凸包
{sort(p,p+n);int m=0;for(int i=0; i<n; ++i){while(m>1&&Cross(convex[m-1]-convex[m-2],p[i]-convex[m-2])<0){m--;}convex[m++]=p[i];}int k=m;for(int i=n-2; i>=0; --i){while(m>1&&Cross(convex[m-1]-convex[m-2],p[i]-convex[m-2])<0){m--;}convex[m++]=p[i];}if(n>1)m--;return m;
}
Point intersection(Point p1,Point p2,Point l1,Point l2)//交点坐标
{Point ret=p1;//首先计算直线是否平行double t=((p1.x-l1.x)*(l1.y-l2.y)-(p1.y-l1.y)*(l1.x-l2.x))/((p1.x-p2.x)*(l1.y-l2.y)-(p1.y-p2.y)*(l1.x-l2.x));ret.x+=(p2.x-p1.x)*t;ret.y+=(p2.y-p1.y)*t;return ret;//线段交点另外判断线段相交(同时判断是否平行)
}
Point now[Max],convex[Max];
double area,per;
double GetArea(Line up,Line down,Line left,Line right)//根据矩形四条线求面积
{Point minx=intersection(left.p,left.p+left.v,down.p,down.p+down.v);Point miny=intersection(right.p,right.p+right.v,down.p,down.p+down.v);Point manx=intersection(left.p,left.p+left.v,up.p,up.p+up.v);return Dis(minx,manx)*Dis(minx,miny);
}
double GetPer(Line up,Line down,Line left,Line right)
{Point minx=intersection(left.p,left.p+left.v,down.p,down.p+down.v);Point miny=intersection(right.p,right.p+right.v,down.p,down.p+down.v);Point manx=intersection(left.p,left.p+left.v,up.p,up.p+up.v);return (Dis(minx,manx)+Dis(minx,miny))*2;
}
Vector Rotate(Vector A,double rad) //向量A逆时针旋转rad
{
return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
void RotateStuck(int n)//旋转卡壳枚举矩形
{for(int i=0;i<n;++i){convex[i+n]=convex[i];convex[i+n+n]=convex[i];}area=per=Inf;Line up,down,left,right;//四条直线int i=0,j=0,k=0,l=0;//四条线的位置for(; i<n; ++i)//枚举上这条线,则可以确定其他
    {up=Line(convex[i],convex[i+1]-convex[i]);//其他三条直线所在的点与上这条线成单峰函数k=max(i,k);//每次是逆时针旋转,保证是凸包上一条线或者后面的线while(Cross(Rotate(up.v,Pi/2),convex[k+1]-convex[k])<0)//通过旋转来判断k++;left=Line(convex[k],Rotate(up.v,Pi/2));j=max(k,j);while(Cross(Rotate(up.v,Pi),convex[j+1]-convex[j])<0)j++;down=Line(convex[j],Rotate(up.v,Pi));l=max(j,l);while(Cross(Rotate(up.v,3*Pi/2),convex[l+1]-convex[l])<0)l++;right=Line(convex[l],Rotate(up.v,3*Pi/2));area=min(area,GetArea(up,down,left,right));per=min(per,GetPer(up,down,left,right));}return ;
}
int main()
{int n;while(~scanf("%d",&n)&&n){for(int i=0; i<n; ++i){scanf("%lf %lf",&now[i].x,&now[i].y);}int m= ConvexHull(now,n,convex);RotateStuck(m);printf("%.2f %.2f\n",area,per);}return 0;
}

转载于:https://www.cnblogs.com/zhuanzhuruyi/p/6371875.html

UVA 12307 Smallest Enclosing Rectangle(旋转卡壳)相关推荐

  1. CF1578F Framing Pictures 旋转卡壳+积分

    CF1578F Framing Pictures 旋转卡壳+积分 Framing Pictures 题目描述 Life has been discovered on Venus! What is mo ...

  2. 旋转卡壳算法求最小外接矩形代码

    旋转卡壳原理:旋转卡壳详解_大学要有梦想的博客-CSDN博客_旋转卡壳 思路: 1.选择卡壳算法用于求凸多边形的最小外接矩形 1.多边形最小的外接矩形一定是以多边形的的一条边为底的一部分 2.通过这条 ...

  3. 算法复习——凸包加旋转卡壳(poj2187)

    题目: Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest ...

  4. Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

    \(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接 ...

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

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

  6. 算法学习:计算几何旋转卡壳

    [定义] [对踵点]多边形上存在平行切线的两点 [多边形半径]多边形上任意两点的最大长度 [旋转卡壳] 选取y轴上,最高和最低的两个点,令两条平行于x轴的线切过这两点 然后我们开始让这两条线旋转 当一 ...

  7. bzoj 1069 [SCOI2007]最大土地面积——旋转卡壳

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1069 发现 n 可以 n^2 .所以枚举对角线,分开的两部分三角形就可以旋转卡壳了. 注意坐 ...

  8. 【BZOJ1185】【HNOI2007】最小矩形覆盖(凸包+旋转卡壳)

    传送门 题意:求最小矩阵覆盖 有这样一个结论:矩阵一定有一条边在凸包上(不会证) 那可以枚举每条边 同时旋转卡壳 只是这时不只维护一个对踵点对,同时在左右侧再维护一个最远点 可以发现左右最远点一定是和 ...

  9. poj 2079(旋转卡壳)

    题意:求出平面内的点集所组成的面积最大的三角形. 解题思路:考虑凸包+旋转卡壳.面积最大的三角形的三点必定在凸包的顶点上,只不过这里要注意,三角形的边不一定就是凸包的边,有可能三角形相邻两点是横跨凸包 ...

  10. poj 2187 Beauty Contest (凸包: 最远点对,最长直径 , 旋转卡壳法)

    http://poj.org/problem?id=2187 题意: 最长的点对近距离的平方: 题解: 旋转卡壳法, 要注意的地方是,有 所有点共线的情况,所以,(求凸包时)要将,共线点去出 :    ...

最新文章

  1. 2021-08-09 图像灰度二值化
  2. 《调色师手册:电影和视频调色专业技法(第2版)》——调色师该何时介入?...
  3. linux 进程间通信 命名管道FIFO的原理与使用
  4. 多益网络 视频面试面试总结20180816
  5. T-SQL远程数据库备份还原
  6. python入门——P39类和对象:拾遗
  7. Unity 项目 - Ruby‘s Adventure 学习笔记
  8. php医院数据库设计,检查我的数据库设计/ PHP / MySQL
  9. 统计学习方法读书笔记3-感知机SVM
  10. 虚函数和虚析构函数的实现原理--虚函数表
  11. 对自己编译的文件(exe/dll)进行签名的实践(Windows)
  12. Oct.14 华为数通部算法岗面经
  13. powerdesign如何利用表导出sql
  14. Flutter 旋转动画
  15. opengl——贴图
  16. 捋一捋Python中的Dict(下)
  17. html5水墨背景,好看的水墨画背景图片
  18. 1.通过PADS Logic创建原件类型和逻辑封装
  19. Linux: 查看文件和文件夹大小的df和du命令
  20. 内部培训——规范原则与重构

热门文章

  1. RS编译码理论介绍与MATLAB性能仿真
  2. 体绘制加速技术之数据异步传输
  3. app运营中,如何提高用户活跃度?
  4. 写给三维建模入门小白的建议
  5. Java中2 5D游戏(斜45度角)的设计与实现 1
  6. 网站广告的盈利模式详解
  7. 网页设计如何排成一列_网页排版设计中对齐技巧能让网站产生高端感(下)
  8. 增加linux vg 空间大小_Desperate struggle
  9. OJ 2309 Problem C Lemon
  10. opencv convertTo函数