题意(中问题直接粘吧)
矩形面积

Problem Description

小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些矩形包围起来的面积最小的矩形的面积是多少。

 

Input

第一行一个正整数 T,代表测试数据组数(1≤T≤20),接下来 T 组测试数据。

每组测试数据占若干行,第一行一个正整数 N(1≤N<≤1000),代表矩形的数量。接下来 N 行,每行 8 个整数x1,y1,x2,y2,x3,y3,x4,y4,代表矩形的四个点坐标,坐标绝对值不会超过10000。

 

Output

对于每组测试数据,输出两行:

第一行输出"Case #i:",i 代表第 i 组测试数据。

第二行包含1 个数字,代表面积最小的矩形的面积,结果保留到整数位。

 

Sample Input

2

2

5 10 5 8 3 10 3 8

8 8 8 6 7 8 7 6

1

0 0 2 2 2 0 0 2

 

Sample Output

Case #1:

17

Case #2:

4

思路:

      矩形不是凸出来的东西,吐出来的部分肯定是点,怎么连接边都在点连线的里面,这样就是求n*4个点的最小矩形覆盖面积,直接来个模板就行了,一开始用自己以前写的一个三分的方法来旋转角度去求,一直wa,感觉那个只能求正方形吧,这个是在网上找的,还有第一次暴栈了,记得加上外挂开战的那个东西。



#pragma comment(linker, "/STACK:1024000000,1024000000")

#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm> using namespace std; typedef double typev;
const double eps = 1e-8;
const int N = 50005;
int sign(double d){
return d < -eps ? -1 : (d > eps);
}
struct point{
typev 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;
}
}ps[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 = 50005; //点数的最大值
point ps[N+5]; //逆时针存储多边形的点,[0,pn-1]存储点
int pn; //点数
poly() { pn = 0; }
//加进一个点
void push(point tp){
ps[pn++] = tp;
}
//第k个位置
int trim(int k){
return (k+pn)%pn;
}
void clear(){ pn = 0; }
};
//返回含有n个点的点集ps的凸包
poly graham(point* ps, int n){
sort(ps, ps + n, cmp);
poly ans;
if(n <= 2){
for(int i = 0; i < n; i++){
ans.push(ps[i]);
}
return ans;
}
ans.push(ps[0]);
ans.push(ps[1]);
point* tps = ans.ps;
int top = -1;
tps[++top] = ps[0];
tps[++top] = ps[1];
for(int i = 2; i < n; i++){
while(top > 0 && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) top--;
tps[++top] = ps[i];
}
int tmp = top; //注意要赋值给tmp!
for(int i = n - 2; i >= 0; i--){
while(top > tmp && xmul(tps[top - 1], tps[top], tps[top - 1], ps[i]) <= 0) 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+(1-u)*ed.x;
ans.y = u*st.y+(1-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 <= 2){
ds[0] = con[0]; ds[1] = con[1];
ds[2] = con[1]; ds[3] = con[0];
ans=0;
}else{
int l, r, u;
double tmp, len;
con[cn] = con[0];
ans = 1e40;
l = i = 0;
while(dmul(con[i], con[i+1], con[i], con[l])
>= dmul(con[i], con[i+1], con[i], con[(l-1+cn)%cn])){
l = (l-1+cn)%cn;
}
for(r=u=i = 0; i < cn; i++){
while(xmul(con[i], con[i+1], con[i], con[u])
<= xmul(con[i], con[i+1], con[i], con[(u+1)%cn])){
u = (u+1)%cn;
}
while(dmul(con[i], con[i+1], con[i], con[r])
<= dmul(con[i], con[i+1], con[i], con[(r+1)%cn])){
r = (r+1)%cn;
}
while(dmul(con[i], con[i+1], con[i], con[l])
>= dmul(con[i], con[i+1], con[i], con[(l+1)%cn])){
l = (l+1)%cn;
}
tmp = dmul(con[i], con[i+1], con[i], con[r]) - dmul(con[i], con[i+1], con[i], con[l]);
tmp *= xmul(con[i], con[i+1], con[i], con[u]);
tmp /= dist2(con[i], con[i+1]);
len = xmul(con[i], con[i+1], con[i], con[u])/dist(con[i], con[i+1]);
if(sign(tmp - ans) < 0){
ans = tmp;
ds[0] = getRoot(con[l], con[i], con[i+1]);
ds[1] = getRoot(con[r], con[i+1], con[i]);
ds[2] = change(con[i], con[i+1], ds[1], len);
ds[3] = change(con[i], con[i+1], ds[0], len);
}
}
}
return ans+eps;
} int main ()
{
int t ,n ,i ,NN ,cas = 1;
point ds[10];
scanf("%d" ,&t);
while(t--)
{
scanf("%d" ,&NN);
int n = 0;
for(i = 1 ;i <= NN ;i ++)
{
for(int j = 1 ;j <= 4 ;j ++)
{
scanf("%lf %lf" ,&ps[n].x ,&ps[n].y);
n++;
}
}
double ans = getMinAreaRect(ps ,n ,ds);
printf("Case #%d:\n" ,cas ++);
printf("%.0lf\n" ,ans);
}
return 0;
}

hdu5251最小矩形覆盖的更多相关文章

  1. [hdu5251]矩形面积 旋转卡壳求最小矩形覆盖

    旋转卡壳求最小矩形覆盖的模板题. 因为最小矩形必定与凸包的一条边平行,则枚举凸包的边,通过旋转卡壳的思想去找到其他3个点,构成矩形,求出最小面积即可. #include<cstdio> # ...

  2. bzoj 1185 旋转卡壳 最小矩形覆盖

    题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点 这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性 ...

  3. 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖

    1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1945  Solve ...

  4. BZOJ:1185: [HNOI2007]最小矩形覆盖

    1185: [HNOI2007]最小矩形覆盖 这计算几何……果然很烦…… 发现自己不会旋转卡壳,补了下,然后发现求凸包也不会…… 凸包:找一个最左下的点,其他点按照与它连边的夹角排序,然后维护一个栈用 ...

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

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

  6. TZOJ 2392 Bounding box(正n边形三点求最小矩形覆盖面积)

    描述 The Archeologists of the Current Millenium (ACM) now and then discover ancient artifacts located ...

  7. 【BZOJ1185】[HNOI2007]最小矩形覆盖(凸包,旋转卡壳)

    [BZOJ1185][HNOI2007]最小矩形覆盖(凸包,旋转卡壳) 题面 BZOJ 洛谷 题解 最小的矩形一定存在一条边在凸包上,那么枚举这条边,我们还差三个点,即距离当前边的最远点,以及做这条边 ...

  8. LG3187 [HNOI2007]最小矩形覆盖

    题意 题目描述 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点坐标 输入输出格式 输入格式: 第一行为一个整数n(3<=n<=50000),从第2至第 ...

  9. bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包

    [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 2081  Solved: 920 ...

随机推荐

  1. Java变量-常量-作用域

    public class Demo05 { /* 变量的命名规范:见名知意 1.类变量/实例变量/局部变量使用驼峰原则命名 2.类名使用Pascal命名法 3.常量名使用大写字母和下划线 4.驼峰原则 ...

  2. java 基础语法学习

    kuangstudy 注释 单行注释 多行注释 文档注释 public class HelloWorld { public static void main(String[] args) { //单行 ...

  3. Java I/O流 04

    I/O流·其他流 序列流 * A:什么是序列流 * 序列流可以把多个字节输入流整合成一个,从序列流中读取数据时,将从被整合的第一个流开始,读完后再读下一个 * B:使用方式 * 整合两个:Sequen ...

  4. python学习之基础内容

    python基础内容① 什么是python? -一种计算机语言,计算机语言分为 -高级语言:python.java.Ruby.C#.C++...... -基础语言:C语言.汇编 -计算机可以直接执行基 ...

  5. ch1_6_3求解移动字符串问题

    import java.util.Scanner; public class ch1_6_3求解移动字符串问题 { public static void main(String[] args) { / ...

  6. 根据数据渲染DOM树形菜单——中途感想

    根据数据渲染DOM树形菜单,这个需求做了几天了.一开始觉得用while也可以实现一层一层查找数据,但后来发现while还是做不到,因为我查找这个动作必须有进入有出来然后进入下一个条目,但while只能 ...

  7. JVM虚拟机知识问答总结(简单复习,快速回忆!)

    写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...

  8. [源码解析] 并行分布式框架 Celery 之架构 (1)

    [源码解析] 并行分布式框架 Celery 之架构 (1) 目录 [源码解析] 并行分布式框架 Celery 之架构 (1) 0x00 摘要 0x01 Celery 简介 1.1 什么是 Celery ...

  9. 拖拽方式生成Vue用户界面

      前一阵子拜访了一些小伙伴,大家都表示苦前端太久了,需要花费不少时间在前端开发上.本着在不损失灵活性的前提下尽可能提高开发效率的原则,作者尝试在框架内集成了拖拽方式生成Vue用户界面的功能作为补充, ...

  10. KubeEdge云边协同设计原理

    云端组件CloudCore与k8s Master的关系 从黑盒角度看,CloudCore就是k8s的一个插件,它是非侵入的来扩展k8s的一部分功能,将原来云上的节点映射到边缘端进行管理,一个Cloud ...