题意:

给定n个点,求一个将所有点覆盖的最小面积的矩形。

思路:

首先结果矩形一定有一条边在点集的凸包边上。因此我们枚举每一条边,只要求出其对应的 r(垂直距离最远的点)、p(距离线正向最远的点)、q(距离线负向最远的点),即可求出这个矩形的面积。

首先求r,r点即为(ps[i],ps[i+1]),(ps[i],r)叉积最大的点。然后求p,p点即为(ps[i],ps[i+1]),(ps[i],p)点积最大的点。最后求q,q即为(ps[i],ps[i+1]),(ps[i],q)点积最小的点。因此在n^2的复杂度内即可求出该矩形。

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x) cout << "x: " << x << endl;
#define LOG2(x,y) cout << "x: " << x << ", y: " << y << endl;
#define LOG3(x,y,z) cout << "x: " << x << ", y: " << y << ", z: " << z << endl;
#define LOG4(x,y,z,h) cout << "x: " << x << ", y: " << y << ", z: " << z << ", h: " << h << endl;
#define pi acos(-1.0)
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y)) //向量(p1,p2)与(p1,p3)叉乘
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3)) //判断正负,顺时针为负, 为0则代表三点共线
using namespace std;//实数比较
typedef double db;
const db EPS = 1e-9;
inline int sign(db a) {return a < -EPS ? -1 : a > EPS; } //返回-1表示a < 0, 1表示a > 0, 0表示a = 0
inline int cmp(db a, db b) {return sign(a-b); } //返回-1表示a < b, 1表示a > b,0表示 a==b//点类
struct P {db x,y;P() {}P(db _x, db _y) : x(_x), y(_y) {}P operator+(P p) { return {x+p.x, y+p.y}; }P operator-(P p) { return {x-p.x, y-p.y}; }P operator*(db d) { return {x*d, y*d}; }P operator/(db d) { return {x/d, y/d}; }db dot(P p) { return x*p.x+y*p.y; }   //点积db det(P p) { return x*p.y-y*p.x; } //叉积P rot(db an) { return {x*cos(an)-y*sin(an),x*sin(an)+y*cos(an)}; } //旋转db abs() { return sqrt(abs2()); }db abs2() { return x*x+y*y; }db disTo(P p) { return (*this-p).abs(); }//此时在x负半轴上的点, 排序结果是最小的。如果去掉sign(x)>=0, 则排序结果是最大的int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); } //判断该点是否在x轴上方或x轴上bool operator<(P p) const {int c = cmp(x, p.x);if (c) return c == -1;    //先判断x大小return cmp(y, p.y) == -1; //再判断y大小}bool operator==(P p) const {return cmp(x, p.x) == 0 && cmp(y, p.y) == 0;}bool operator!=(P p) const{return (cmp(x, p.x) || cmp(y,p.y));}
}tmp;db dot(P A, P B, P C){return (B-A).dot(C-A);
}vector<P> convexHull(vector<P> ps) {int n = ps.size(); if(n <= 1) return ps;sort(ps.begin(),ps.end());vector<P> qs(n*2); int k = 0;for(int i = 0; i < n; qs[k++] = ps[i++])while(k > 1 && crossOp(qs[k-2],qs[k-1],ps[i]) <= 0) --k;    //把 <= 改成 <, 即可将凸包边上的点也包括在凸包中, 不稳定凸包问题 for(int i = n-2, t = k; i >= 0; qs[k++] = ps[i--])while(k > t && crossOp(qs[k-2],qs[k-1],ps[i]) <= 0) --k;qs.resize(k-1);return qs;
}db minRectangleCover(vector<P> ps){//凸包点集顺序按逆时针int n = ps.size();   if(n < 3) return 0.0;ps.push_back(ps[0]);db ans = -1;int r = 1, p = 1, q;for(int i = 0; i < n; i++){//求出离边 ps[i]-ps[i+1] 最远的点 rwhile(sign(cross(ps[i],ps[i+1],ps[r+1])-cross(ps[i],ps[i+1],ps[r])) >= 0) //叉积最大即为到点r到ps[i+1]-ps[i]这条边的距离最大r = (r+1)%n;//卡出 ps[i]-ps[i+1] 方向上正向 n 最远的点 pwhile(sign(dot(ps[i],ps[i+1],ps[p+1])-dot(ps[i],ps[i+1],ps[p])) >= 0) //正向最远即为点积最大p = (p+1)%n;if(i == 0) q = p;//卡出 ps[i]-ps[i+1]方向上负向最远的点 qwhile(sign(dot(ps[i],ps[i+1],ps[q+1]) - dot(ps[i],ps[i+1],ps[q])) <= 0)  //负向最大即为点积最小q = (q+1)%n;db d = ps[i].disTo(ps[i+1]);    //线段长度d = d*d;//叉积求出高,点积求出底边db tmp = cross(ps[i],ps[i+1],ps[r]) *     (dot(ps[i],ps[i+1],ps[p])-dot(ps[i],ps[i+1],ps[q]))/d;if(ans < 0 || ans > tmp) ans = tmp;}return ans;
}int main()
{int n,_;scanf("%d",&_);rep(k,1,_){scanf("%d",&n);if(n == 0) break;vector<P> tp;tp.clear();// scanf("%d",&n);n *= 4;rep(i,1,n){db x,y;scanf("%lf%lf",&x,&y);tmp = {x,y};tp.push_back(tmp);}tp = convexHull(tp);// rep(i,0,tp.size()-1) printf("%lf,%lf\n",tp[i].x,tp[i].y);db ans = minRectangleCover(tp);printf("Case #%d:\n",k);printf("%.0f\n",ans);}return 0;
}

【HDU 5251】矩形面积【凸包 最小矩形覆盖】相关推荐

  1. 设计一个矩形类,完成计算矩形面积和显示矩形属性的功能。

    / /* [基本题]设计一个矩形类,完成计算矩形面积和显示矩形属性的功能. */ #include<iostream> using namespace std; class Retangl ...

  2. HDU 3265(矩形面积并-分割矩形)

    Posters Problem Description 有很多海报,每个海报都被减去了一个矩形(可能全减),现在给出没张海报的位置,求它们的面积并. 保证坐标在(0, 0)到(50000, 50000 ...

  3. 语音计算矩形面积_LeetCode85-最大矩形

    今天在制作书签的时候 突然想到了一个问题 如果要送给未来的女朋友一个书签 上面该写些什么话 哈哈哈哈哈哈哈哈哈 The Spring is coming! 想了一会儿,觉得这句话最合适 To xxx: ...

  4. 850.矩形面积 II 【矩形的分解】

    题解 启发式解法-矩形分解 思路 因为多个矩形重叠部分的面积只需要计算一次,因此可以想到将重叠的多个矩形转化为多个不重叠的矩形,最后通过计算不重叠矩形中所有的矩形面积得到答案. 所需要的前置知识,针对 ...

  5. 求圆形矩形面积java_Java求矩形面积和圆形面积的异常处理实例

    题目 有一个圆形和长方形. 都可以获取面积,对于如果如果出现非法值,视为是获取面积出现问题. 问题通过异常来表示. 现在对这个程序进行基本设计 代码如下 package com.liuyanzhao; ...

  6. 01矩阵最大正方形面积、01矩阵最大矩形面积、直方图最大矩形面积

    01矩阵最大正方形面积 题意:给定一个矩阵,其中的元素为0或者1,要求找出其中元素全为1的面积最大的正方形. 题解:动态规划:对每个元素,把以其为右下角,元素全为1的正方形的最长边长记录下来.如果以元 ...

  7. 直方图中最大矩形面积

    原文地址:http://www.geeksforgeeks.org/largest-rectangle-under-histogram/ 注意:本文并未对原文完整翻译,而是结合原文并根据本人理解写出, ...

  8. c语言直方图最大矩形面积,直方图中最大矩形面积(示例代码)

    注意:本文并未对原文完整翻译,而是结合原文并根据本人理解写出,因此部分内容为完整翻译,部分内容为个人理解所写. Largest Rectangle in Histogram 直方图中最大矩形面积 一个 ...

  9. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

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

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

最新文章

  1. SVM算法实现光学字符识别
  2. tf.keras.losses.SquaredHinge 损失函数 示例
  3. 硬件常见问题及排错思路。
  4. bailian 2754八皇后
  5. 汇编语言王爽第二版-课后答案以及解析
  6. Spark Streaming
  7. [转]序列化悍将Protobuf-Net,入门动手实录
  8. HTML5权威指南 11.通信API
  9. php设置路径别名,设置别名php = / bin / php56,但今天它已恢复为原始路径:/ bin / php...
  10. 学校后勤物资管理系统(数据库课程设计)
  11. matlab正弦函数傅里叶变换,正弦函数及其傅里叶变换 二
  12. 日本JAFFE表情库
  13. 实现一个计算体脂率的程序
  14. 项目开发中dev、test和prod是什么意思
  15. 【Dos默认路径设置】
  16. 第二章 大数据技术概述
  17. 查找——图文翔解RadixTree(基数树)
  18. AR智能眼镜会成未来趋势
  19. 2/28 A - 化学 (编译器选 GNU G++)
  20. 计算机主机的声音线是哪个好,电脑显示器连接线哪种接口好|VGA、HDMI视频接口选哪个好...

热门文章

  1. Linux 建立ftp站点
  2. mootools-1.2.1-core.js在IE中显示不了图像翻页
  3. linux之sed使用
  4. qi接收启动协议_无线充电Qi通信协议分析
  5. 服务器更新维护尚未全部完成,03月07日全部服务器更新维护公告
  6. android studio发包,androidstudio使用gradle打包配置详解.pdf
  7. oracle创建默认序列号,PLS-00103:为序列号oracle创建触发器(PLS-00103: Create trigger for sequence number oracle)...
  8. crontab命令 :Linux下定时执行脚本
  9. js sdk demo java_微信JS-SDK DEMO页面和示例代码
  10. 【2019杭电多校第七场1011=HDU6656】Kejin Player(期望dp+递推+逆元)