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

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

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

   求另三条边时首先方向是确定了的,找点就是旋转卡壳,思想就是:枚举的任意两条边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=<<;
const ll INF=1LL<<;
const double Pi=acos(-1.0);
const int Mod=1e9+;
const int Max=;
struct Point
{
double x,y;
Point(double x=,double y=):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)<||zero(x-a.x)&&sgn(y-a.y)<;
}
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=;
for(int i=; i<n; ++i)
{
while(m>&&Cross(convex[m-]-convex[m-],p[i]-convex[m-])<)
{
m--;
}
convex[m++]=p[i];
}
int k=m;
for(int i=n-; i>=; --i)
{
while(m>&&Cross(convex[m-]-convex[m-],p[i]-convex[m-])<)
{
m--;
}
convex[m++]=p[i];
}
if(n>)
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))*;
}
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=;i<n;++i)
{
convex[i+n]=convex[i];
convex[i+n+n]=convex[i];
}
area=per=Inf;
Line up,down,left,right;//四条直线
int i=,j=,k=,l=;//四条线的位置
for(; i<n; ++i)//枚举上这条线,则可以确定其他
{
up=Line(convex[i],convex[i+]-convex[i]);//其他三条直线所在的点与上这条线成单峰函数
k=max(i,k);//每次是逆时针旋转,保证是凸包上一条线或者后面的线
while(Cross(Rotate(up.v,Pi/),convex[k+]-convex[k])<)//通过旋转来判断
k++;
left=Line(convex[k],Rotate(up.v,Pi/));
j=max(k,j);
while(Cross(Rotate(up.v,Pi),convex[j+]-convex[j])<)
j++;
down=Line(convex[j],Rotate(up.v,Pi));
l=max(j,l);
while(Cross(Rotate(up.v,*Pi/),convex[l+]-convex[l])<)
l++;
right=Line(convex[l],Rotate(up.v,*Pi/));
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=; 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 ;
}

UVA 12307 Smallest Enclosing Rectangle(旋转卡壳)的更多相关文章

  1. UVA 12307 Smallest Enclosing Rectangle

    https://vjudge.net/problem/UVA-12307 求覆盖所有点的最小矩形面积.周长 相当于求凸包的最小面积外接矩形.最小周长外接矩形 结论: 这个矩形一定有一条边和凸包上一条边 ...

  2. 此坑待填 离散化思想和凸包 UVA - 10173 Smallest Bounding Rectangle

    Smallest Bounding Rectangle Given the Cartesian coordinates of n(>0)2-dimensional points, write a ...

  3. UVA 4728 Squares(凸包+旋转卡壳)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17267 [思路] 凸包+旋转卡壳 求出凸包,用旋转卡壳算出凸包的直 ...

  4. UVa 1453 - Squares 旋转卡壳求凸包直径

    旋转卡壳求凸包直径. 参考:http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html #include <cstdio> ...

  5. UVa1453或La4728 凸包+枚举(或旋转卡壳)

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  6. 1393: Robert Hood 旋转卡壳 凸包

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1393 http://poj.org/problem?id=2187 Beauty Contest ...

  7. POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳

    题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...

  8. 【BZOJ 1069】【SCOI 2007】最大土地面积 凸包+旋转卡壳

    因为凸壳上对踵点的单调性所以旋转卡壳线性绕一圈就可以啦啦啦--- 先求凸包,然后旋转卡壳记录$sum1$和$sum2$,最后统计答案就可以了 #include<cmath> #includ ...

  9. 【POJ 2187】Beauty Contest(凸包直径、旋转卡壳)

    给定点集的最远两点的距离. 先用graham求凸包.旋(xuán)转(zhuàn)卡(qiǎ)壳(ké)求凸包直径. ps:旋转卡壳算法的典型运用 http://blog.csdn.net/hanch ...

随机推荐

  1. dos下查找进程,如果找到echo find并结束该进程

    @echo offset var=chromedriver.exetasklist | findstr "%var%" && echo findtaskkill / ...

  2. sql server 2008获取表的字段注释

    SELECT 表名 then d.name else '' end, 表说明 then isnull(f.value,'') else '' end, 字段序号=a.colorder, 字段名=a.n ...

  3. 【穿插】Python基础之文件、文件夹的创建,对上一期代码进行优化

    在上一期妹子图的爬虫教程中,我们将图片都保存在了代码当前目录下,这样并不便于浏览,我们应该将同一个模特的图片都放在一个文件夹中. 今天我们就简单讲一下Python下如何创建文件.文件夹,今后就可以用上 ...

  4. Pycharm中目前用到的快捷键

    1.批量注释:Ctrl+/ 2.缩进\不缩进:Tab\Shift+Tab 3.运行:Ctrl+Shift+F10 4.撤销\反撤销:Ctrl+z\Ctrl+shift+z 5.当光标在代码中间,如何回 ...

  5. CAS单点登录------未认证授权服务

    问题背景:之前我使用的127.0.0.1进行CAS 直接url 进行过滤! 后来我用nginx 进行反向代理 出现问题:  如下图 第一眼,就在内心想,草这什么鬼! 麻蛋!     ON! 调试了五分 ...

  6. SpringBoot使用H2内嵌数据库

    1.驱动 我们知道,JDBC是JDK自带的接口规范,不同的数据库有不同的实现,只需要引入相应的驱动包即可. 在使用MySQL数据库时,引入的是MySQL驱动,相应的,使用H2数据库时,也需要引入H2驱 ...

  7. of 循环 改变 对象值 对const的理解 对象的字面量 计算属性

    const arr = [{a:23,b:34},{a:123,b:134}]console.log(arr)for (let v of arr){console.log(v)const old = ...

  8. JavaScript和jQuery改变标签内容

    HTML: <div id="mazey">content</div> JavaScript: var mazey=document.getElementB ...

  9. Docker介绍及优缺点对比分析

    1.什么是Docker Docker最初是dotCloud公司创始人Solomon Hykes在法国期间发起的一个公司内部项目,于2013年3月以Apache 2.0授权协议开源,主要项目代码在Git ...

  10. pycharm中导入自写模块时,模块下出现红线

    问题描述: 在pycharm中导入自己写的模块时,得不到智能提示,并在模块名下出现下红线,但是代码可以执行,错误提示为下图所示: 原因:出现 以上情况,是因为文件目录设置的问题,pycharm中的最上 ...