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

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

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

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

  1. #include<set>
  2. #include<map>
  3. #include<queue>
  4. #include<stack>
  5. #include<cmath>
  6. #include<vector>
  7. #include<string>
  8. #include<cstdio>
  9. #include<cstring>
  10. #include<iomanip>
  11. #include<stdlib.h>
  12. #include<iostream>
  13. #include<algorithm>
  14. using namespace std;
  15. #define eps 1E-8
  16. /*注意可能会有输出-0.000*/
  17. #define sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
  18. #define cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
  19. #define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
  20. #define mul(a,b) (a<<b)
  21. #define dir(a,b) (a>>b)
  22. typedef long long ll;
  23. typedef unsigned long long ull;
  24. const int Inf=<<;
  25. const ll INF=1LL<<;
  26. const double Pi=acos(-1.0);
  27. const int Mod=1e9+;
  28. const int Max=;
  29. struct Point
  30. {
  31. double x,y;
  32. Point(double x=,double y=):x(x),y(y) {};
  33. inline Point operator-(const Point& a)const
  34. {
  35. return Point(x-a.x,y-a.y);
  36. }
  37. inline bool operator<(const Point& a)const
  38. {
  39. return sgn(x-a.x)<||zero(x-a.x)&&sgn(y-a.y)<;
  40. }
  41. inline Point operator+(const Point& a)const
  42. {
  43. return Point(x+a.x,y+a.y);
  44. }
  45. inline bool operator!=(const Point& a)const
  46. {
  47. return !(zero(x-a.x)&&zero(y-a.y));
  48. }
  49. };
  50. typedef Point Vector;
  51. struct Line
  52. {
  53. Point p;
  54. Vector v;
  55. double ang;//极角
  56. Line() {};
  57. Line(Point p,Vector v):p(p),v(v)
  58. {
  59. ang=atan2(v.y,v.x);
  60. }
  61. inline bool operator<(const Line& L)const
  62. {
  63. return ang<L.ang;
  64. }
  65. };
  66. double Dis(Point A,Point B)
  67. {
  68. return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
  69. }
  70. double Cross(Vector A,Vector B)
  71. {
  72. return A.x*B.y-A.y*B.x;
  73. }
  74. int ConvexHull(Point *p,int n,Point *convex)//求凸包
  75. {
  76. sort(p,p+n);
  77. int m=;
  78. for(int i=; i<n; ++i)
  79. {
  80. while(m>&&Cross(convex[m-]-convex[m-],p[i]-convex[m-])<)
  81. {
  82. m--;
  83. }
  84. convex[m++]=p[i];
  85. }
  86. int k=m;
  87. for(int i=n-; i>=; --i)
  88. {
  89. while(m>&&Cross(convex[m-]-convex[m-],p[i]-convex[m-])<)
  90. {
  91. m--;
  92. }
  93. convex[m++]=p[i];
  94. }
  95. if(n>)
  96. m--;
  97. return m;
  98. }
  99. Point intersection(Point p1,Point p2,Point l1,Point l2)//交点坐标
  100. {
  101. Point ret=p1;//首先计算直线是否平行
  102. double t=((p1.x-l1.x)*(l1.y-l2.y)-(p1.y-l1.y)*(l1.x-l2.x))
  103. /((p1.x-p2.x)*(l1.y-l2.y)-(p1.y-p2.y)*(l1.x-l2.x));
  104. ret.x+=(p2.x-p1.x)*t;
  105. ret.y+=(p2.y-p1.y)*t;
  106. return ret;//线段交点另外判断线段相交(同时判断是否平行)
  107. }
  108. Point now[Max],convex[Max];
  109. double area,per;
  110. double GetArea(Line up,Line down,Line left,Line right)//根据矩形四条线求面积
  111. {
  112. Point minx=intersection(left.p,left.p+left.v,down.p,down.p+down.v);
  113. Point miny=intersection(right.p,right.p+right.v,down.p,down.p+down.v);
  114. Point manx=intersection(left.p,left.p+left.v,up.p,up.p+up.v);
  115. return Dis(minx,manx)*Dis(minx,miny);
  116. }
  117. double GetPer(Line up,Line down,Line left,Line right)
  118. {
  119. Point minx=intersection(left.p,left.p+left.v,down.p,down.p+down.v);
  120. Point miny=intersection(right.p,right.p+right.v,down.p,down.p+down.v);
  121. Point manx=intersection(left.p,left.p+left.v,up.p,up.p+up.v);
  122. return (Dis(minx,manx)+Dis(minx,miny))*;
  123. }
  124. Vector Rotate(Vector A,double rad) //向量A逆时针旋转rad
  125. {
  126. return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
  127. }
  128. void RotateStuck(int n)//旋转卡壳枚举矩形
  129. {
  130. for(int i=;i<n;++i)
  131. {
  132. convex[i+n]=convex[i];
  133. convex[i+n+n]=convex[i];
  134. }
  135. area=per=Inf;
  136. Line up,down,left,right;//四条直线
  137. int i=,j=,k=,l=;//四条线的位置
  138. for(; i<n; ++i)//枚举上这条线,则可以确定其他
  139. {
  140. up=Line(convex[i],convex[i+]-convex[i]);//其他三条直线所在的点与上这条线成单峰函数
  141. k=max(i,k);//每次是逆时针旋转,保证是凸包上一条线或者后面的线
  142. while(Cross(Rotate(up.v,Pi/),convex[k+]-convex[k])<)//通过旋转来判断
  143. k++;
  144. left=Line(convex[k],Rotate(up.v,Pi/));
  145. j=max(k,j);
  146. while(Cross(Rotate(up.v,Pi),convex[j+]-convex[j])<)
  147. j++;
  148. down=Line(convex[j],Rotate(up.v,Pi));
  149. l=max(j,l);
  150. while(Cross(Rotate(up.v,*Pi/),convex[l+]-convex[l])<)
  151. l++;
  152. right=Line(convex[l],Rotate(up.v,*Pi/));
  153. area=min(area,GetArea(up,down,left,right));
  154. per=min(per,GetPer(up,down,left,right));
  155. }
  156. return ;
  157. }
  158. int main()
  159. {
  160. int n;
  161. while(~scanf("%d",&n)&&n)
  162. {
  163. for(int i=; i<n; ++i)
  164. {
  165. scanf("%lf %lf",&now[i].x,&now[i].y);
  166. }
  167. int m= ConvexHull(now,n,convex);
  168. RotateStuck(m);
  169. printf("%.2f %.2f\n",area,per);
  170. }
  171. return ;
  172. }

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. APP全局异常捕获,并保存本地文件

    public class CrashHandler implements Thread.UncaughtExceptionHandler { public static final String TA ...

  2. Java Random 含参与不含参构造函数的区别

    ##Random 通常用来作为随机数生成器,它有两个构造方法: Random random = new Random(); Random random2 = new Random(50); 1.不含参 ...

  3. JavaScript的BOM和DOM

    JavaScript的BOM和DOM 1,window对象,所有浏览器都支持window对象,它表示浏览器窗口 BOM(browser Object Model)是指浏览器对象模型,它使JavaScr ...

  4. 《从零开始学Swift》学习笔记(Day 51)——扩展构造函数

    原创文章,欢迎转载.转载请注明:关东升的博客 扩展类型的时候,也可以添加新的构造函数.值类型与引用类型扩展有所区别.值类型包括了除类以外的其他类型,主要是枚举类型和结构体类型. 值类型扩展构造函数 扩 ...

  5. explain the past and guide the future 好的代码的标准:解释过去,指引未来;

    好的代码的标准:解释过去,指引未来: Design philosophies | Django documentation | Django https://docs.djangoproject.co ...

  6. 高德地图API使用

    1.根据地址找经纬度/修改经纬度 marker.setPosition(result.geocodes[0].location); map.setCenter(marker.getPosition() ...

  7. MySQL事务隔离级别,锁(转)

    add by zhj: 本文针对的是MySQL的InnoDB存储引擎,不适用于MySQL的其它存储引擎和其它数据库 原文:MySQL数据库事务隔离级别(Transaction Isolation Le ...

  8. Python获取主机名

    import socket print socket.gethostname()

  9. ShutIt:一个基于 Python 的 shell 自动化框架

    ShutIt是一个易于使用的基于shell的自动化框架.它对基于python的expect库(pexpect)进行了包装.你可以把它看作是“没有痛点的expect”.它可以通过pip进行安装. Hel ...

  10. Java基础—序列化与反序列化(转载)

    转载自: Java序列化与反序列化 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 2.为什么需要序列化 ...