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

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. double型数据的输入和输出--%f和%lf

    scanf函数是通过指针指向变量的. %f告诉scanf函数在所传地址位置上存储一个float型值, 而%lf告诉scanf函数在所传地址位置上存储一个double型值. 这里float和double ...

  2. SpringCloud-服务与注册

    SpringCloud- Eureka服务注册与发现 1.概述 springcloud是一个非常优秀的微服务框架,要管理众多的服务,就需要对这些服务进行治理,管理每个服务与每个服务之间的依赖关系,可以 ...

  3. 面试被吊打系列 - Redis原理

    小张兴冲冲去面试,结果被面试官吊打! 小张: 面试官,你好.我是来参加面试的. 面试官: 你好,小张.我看了你的简历,熟练掌握Redis,那么我就随便问你几个Redis相关的问题吧.首先我的问题是,R ...

  4. layui数据表格-通过点击按钮使数据表格中的字段值增加

    通过点击右侧相对应的操作按钮,对迟到.休假次数实现自增效果 jsp页面代码 //监听行工具事件 table.on('tool(test)', function(obj){ var data = obj ...

  5. C# 应用 - 多线程 4) Task cancel

    1. 操作取消 1.1 步骤 实例化 CancellationTokenSource 对象,该对象管理取消通知并将其发送给单个取消标记 将 CancellationTokenSource.Token ...

  6. JVM实战调优(空格引发的服务异常)

    JVM实战调优 问题描述 某一个项目中有一个文字转语音的服务,使用的是科大讯飞的语音转换服务,需要调用三方服务.因其转换服务是一个耗时操作,官方给的demo使用的是 WebSocket 进行数据转换操 ...

  7. P2089_烤鸡(JAVA语言)

    题目背景 猪猪hanke得到了一只鸡 题目描述 猪猪Hanke特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke吃鸡很特别,为什么特别呢?因为他有10种配料(芥末.孜然等),每种配料可以放1-3克, ...

  8. TEB 、TIB、PEB--Vista 32

    TEB struct TEB typedef struct _TEB { NT_TIB NtTib; PVOID EnvironmentPointer; CLIENT_ID ClientId; PVO ...

  9. Android Studio 分类整理 res/layout 中的布局文件

    •准备工作 新建一个名为 TestLayouts 的项目: 进入 Project 模式: 来到 TestLayouts/app/src/main/res/layout 文件夹下: •分类整理 layo ...

  10. 为了效率,我们可以用的招数 之 strlen

    如果要你写一个计算字符串长度的函数 strlen,应该怎么写?相信你很容易写出如下实现: 1 int strlen_1(const char* str) { 2 int cnt = 0; 3 4 if ...