hdu 5251 包围点集最小矩形 ***
题意:小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少。
求个凸包,矩形的边一定在凸包上,枚举边,求最大值,即为所求,多年不拍几何,直接套了个模板
以后还得练练
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
typedef double typev;
const double eps = 1e-;
const int N = ;
int sign(double d){
return d < -eps ? - : (d > eps);
}
struct point{
typev x, y;
void in()
{
scanf("%lf%lf",&x,&y);
}
point operator-(point d){
point dd;
dd.x = this->x - d.x;
dd.y = this->y - d.y;
return dd;
}
point operator+(point d){
point dd;
dd.x = this->x + d.x;
dd.y = this->y + d.y;
return dd;
}
void read(){ scanf("%lf%lf", &x, &y); }
}ps[N],pd[N];
int n, cn;
double dist(point d1, point d2){
return sqrt(pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0));
}
double dist2(point d1, point d2){
return pow(d1.x - d2.x, 2.0) + pow(d1.y - d2.y, 2.0);
}
bool cmp(point d1, point d2){
return d1.y < d2.y || (d1.y == d2.y && d1.x < d2.x);
}
//st1-->ed1叉乘st2-->ed2的值
typev xmul(point st1, point ed1, point st2, point ed2){
return (ed1.x - st1.x) * (ed2.y - st2.y) - (ed1.y - st1.y) * (ed2.x - st2.x);
}
typev dmul(point st1, point ed1, point st2, point ed2){
return (ed1.x - st1.x) * (ed2.x - st2.x) + (ed1.y - st1.y) * (ed2.y - st2.y);
}
//多边形类
struct poly{
static const int N = ; //点数的最大值
point ps[N+]; //逆时针存储多边形的点,[0,pn-1]存储点
int pn; //点数
poly() { pn = ; }
//加进一个点
void push(point tp){
ps[pn++] = tp;
}
//第k个位置
int trim(int k){
return (k+pn)%pn;
}
void clear(){ pn = ; }
};
//返回含有n个点的点集ps的凸包
poly graham(point* ps, int n){
sort(ps, ps + n, cmp);
poly ans;
if(n <= ){
for(int i = ; i < n; i++){
ans.push(ps[i]);
}
return ans;
}
ans.push(ps[]);
ans.push(ps[]);
point* tps = ans.ps;
int top = -;
tps[++top] = ps[];
tps[++top] = ps[];
for(int i = ; i < n; i++){
while(top > && xmul(tps[top - ], tps[top], tps[top - ], ps[i]) <= ) top--;
tps[++top] = ps[i];
}
int tmp = top; //注意要赋值给tmp!
for(int i = n - ; i >= ; i--){
while(top > tmp && xmul(tps[top - ], tps[top], tps[top - ], ps[i]) <= ) top--;
tps[++top] = ps[i];
}
ans.pn = top;
return ans;
}
//求点p到st->ed的垂足,列参数方程
point getRoot(point p, point st, point ed){
point ans;
double u=((ed.x-st.x)*(ed.x-st.x)+(ed.y-st.y)*(ed.y-st.y));
u = ((ed.x-st.x)*(ed.x-p.x)+(ed.y-st.y)*(ed.y-p.y))/u;
ans.x = u*st.x+(-u)*ed.x;
ans.y = u*st.y+(-u)*ed.y;
return ans;
}
//next为直线(st,ed)上的点,返回next沿(st,ed)右手垂直方向延伸l之后的点
point change(point st, point ed, point next, double l){
point dd;
dd.x = -(ed - st).y;
dd.y = (ed - st).x;
double len = sqrt(dd.x * dd.x + dd.y * dd.y);
dd.x /= len, dd.y /= len;
dd.x *= l, dd.y *= l;
dd = dd + next;
return dd;
}
//求含n个点的点集ps的最小面积矩形,并把结果放在ds(ds为一个长度是4的数组即可,ds中的点是逆时针的)中,并返回这个最小面积。
double getMinAreaRect(point* ps, int n, point* ds){
int cn, i;
double ans;
point* con;
poly tpoly = graham(ps, n);
con = tpoly.ps;
cn = tpoly.pn;
if(cn <= ){
ds[] = con[]; ds[] = con[];
ds[] = con[]; ds[] = con[];
ans=;
}else{
int l, r, u;
double tmp, len;
con[cn] = con[];
ans = 1e40;
l = i = ;
while(dmul(con[i], con[i+], con[i], con[l])
>= dmul(con[i], con[i+], con[i], con[(l-+cn)%cn])){
l = (l-+cn)%cn;
}
for(r=u=i = ; i < cn; i++){
while(xmul(con[i], con[i+], con[i], con[u])
<= xmul(con[i], con[i+], con[i], con[(u+)%cn])){
u = (u+)%cn;
}
while(dmul(con[i], con[i+], con[i], con[r])
<= dmul(con[i], con[i+], con[i], con[(r+)%cn])){
r = (r+)%cn;
}
while(dmul(con[i], con[i+], con[i], con[l])
>= dmul(con[i], con[i+], con[i], con[(l+)%cn])){
l = (l+)%cn;
}
tmp = dmul(con[i], con[i+], con[i], con[r]) - dmul(con[i], con[i+], con[i], con[l]);
tmp *= xmul(con[i], con[i+], con[i], con[u]);
tmp /= dist2(con[i], con[i+]);
len = xmul(con[i], con[i+], con[i], con[u])/dist(con[i], con[i+]);
if(sign(tmp - ans) < ){
ans = tmp;
ds[] = getRoot(con[l], con[i], con[i+]);
ds[] = getRoot(con[r], con[i+], con[i]);
ds[] = change(con[i], con[i+], ds[], len);
ds[] = change(con[i], con[i+], ds[], len);
}
}
}
return ans+eps;
}
int main()
{
int i,j,k;
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
int tt;
scanf("%d",&tt);
int ca=;
while(tt--)
{
printf("Case #%d:\n",ca++);
scanf("%d",&n);
for(i=;i<*n;i++)
{
ps[i].in();
}
double q=getMinAreaRect(ps,*n,pd);
printf("%d\n",int(q+0.5));
}
}
hdu 5251 包围点集最小矩形 ***的更多相关文章
- HDU 5251 矩形面积 (旋转卡壳)
2015年百度之星程序设计大赛 - 初赛(1) 1006 比赛链接:2015年百度之星程序设计大赛 - 初赛(1) 题目链接:HDU 5251 Problem Description 小度熊有一个桌面 ...
- BZOJ 1185: [HNOI2007]最小矩形覆盖-旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标-备忘板子
来源:旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标 BZOJ又崩了,直接贴一下人家的代码. 代码: #include"stdio.h" #include"str ...
- 最小包围多边形(凸包;最小包围点集)——C代码例子
本文来自:http://alienryderflex.com/smallest_enclosing_polygon/ 这个C代码例子需要一群2维点集,如下图所示: 要获得包含这些点的最小多边形如下图所 ...
- hdu5251最小矩形覆盖
题意(中问题直接粘吧)矩形面积 Problem Description 小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少. Input ...
- OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓
本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...
- bzoj 1185 旋转卡壳 最小矩形覆盖
题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点 这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性 ...
- 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1945 Solve ...
- BZOJ:1185: [HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 这计算几何……果然很烦…… 发现自己不会旋转卡壳,补了下,然后发现求凸包也不会…… 凸包:找一个最左下的点,其他点按照与它连边的夹角排序,然后维护一个栈用 ...
- BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1435 Solve ...
随机推荐
- Spring4笔记11--SSH整合2--SpringWeb
SSH 框架整合技术: 2. Spring 在 Web 项目中的使用(建立在Spring与Hibernate整合的基础上): 在 Web 项目中使用 Spring 框架,首先要解决在 Servlet ...
- bzoj 1607 Patting Heads 轻拍牛头
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1607 题解: 题目似乎出错,应为“同时拍打所有所持纸条上的数字能被此牛所持纸条上的数字整除 ...
- linux limits研究
---------------------------------------------------------------------------------------------------- ...
- 04 Effective Go 高效的go语言 重点内容
Effective Go 高效的go语言 Introduction 介绍 Examples 例子 Formatting 格式 Commentary 评论 Names 名字 Package names ...
- 规范命名CSS
作者:词晖链接:https://www.zhihu.com/question/19586885/answer/48933504来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- Codeforces 807C - Success Rate(二分枚举)
题目链接:http://codeforces.com/problemset/problem/807/C 题目大意:给你T组数据,每组有x,y,p,q四个数,x/y是你当前提交正确率,让你求出最少需要再 ...
- linux下Ctrl命令组合
1.键盘组合键操作 ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程.常用于终止正在运行的程序. ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程. ...
- R vs Python:构建data.frame、读取csv与统计描述
一.Python 数据框就是典型的关系型数据库的数据存储形式,每一行是一条记录,每一列是一个属性,最终构成表格的形式,这是数据科学家必须熟悉的最典型的数据结构. 1.构建数据框 import pand ...
- Vue-Socket.io
github地址:https://github.com/MetinSeylan/Vue-Socket.io 安装: npm install vue-socket.io -S 注册: import Vu ...
- Spring整合JDBC以及AOP管理事务
本节内容: Spring整合JDBC Spring中的AOP管理事务 一.Spring整合JDBC Spring框架永远是一个容器,Spring整合JDBC其实就是Spring提供了一个对象,这个对象 ...