题解 P1034 【矩形覆盖】

题面

在平面上有n个点(n≤50),每个点用一对整数坐标表示。例如:当n=4时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一。

这些点可以用k个矩形(1≤k≤4)全部覆盖,矩形的边平行于坐标轴。当k=2时,可用如图二的两个矩形S1,s2覆盖,81,S2面积和为4。问题是当n个点坐标和k给出后,怎样才能使得覆盖所有点的k个矩形的面积之和为最小呢?
约定:覆盖一个点的矩形面积为0;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。

题意

有n个点,找k个矩形包含所有点,使k个矩形和面积和最小。

题解

这道题刚拿到手里的时候是挺棘手的,但是我们看数据范围的大小,是可以暴力枚举的,所以我们可以尝试一下暴力枚举。

建图操作

  1. maps用来存图
  2. ss用来存构建的矩形
    • 立flag来统计这种矩形是否建过
    • 数据最大是4块矩形,可以开小数组
struct maps
{
    int x,y;
} mapp[51];
struct ss
{
    int l,r,u,d;
    bool flag;
} p[5];

判断操作

  1. judge函数枚举四种不成立的情况
  2. in函数判断范围,便于书写judge函数
bool in(ss a, int x, int y)
{
    if (x>=a.l&&x<=a.r&&y>=a.d&&y<=a.u) return 1;
    return 0;
}

bool judge(ss a, ss b)
{
    if (in(a,b.l,b.u)) return 1;
    if (in(a,b.l,b.d)) return 1;
    if (in(a,b.r,b.u)) return 1;
    if (in(a,b.r,b.d)) return 1;
    return 0;
}

dfs操作

  1. 构建好m个矩形
  2. 计算面积和
  3. 每次存最小值
  4. 搜完结束
void dfs(int num)
{
    int value=0;
    for (int i=1; i<=m; i++)
    {
      if (p[i].flag)
      {
        for (int j=i+1; j<=m; j++)
          if (judge(p[i],p[j])) return;
      }
      value+=(p[i].r-p[i].l)*(p[i].u-p[i].d);
    }

    if (value>=ans) return;

    if (num>n){
        ans=value;
        return;
    }

    for (int i=1; i<=m; i++)
    {
        ss tmp=p[i];
        if (p[i].flag==0)
        {
            p[i].flag=1;
            p[i].l=p[i].r=mapp[num].x;
            p[i].u=p[i].d=mapp[num].y;
            dfs(num+1); p[i]=tmp;
            break;
        }
        else
        {
            p[i].r=max(p[i].r,mapp[num].x);
            p[i].l=min(p[i].l,mapp[num].x);
            p[i].u=max(p[i].u,mapp[num].y);
            p[i].d=min(p[i].d,mapp[num].y);
            dfs(num+1);
            p[i]=tmp;
        }
    }
}

代码

#include<cstdio>
#include<iostream>
using namespace std;

struct maps
{
    int x,y;
} mapp[51];
struct ss
{
    int l,r,u,d;
    bool flag;
} p[5];

int n,m,ans=0x7f7f7f7f;

bool in(ss a, int x, int y)
{
    if (x>=a.l&&x<=a.r&&y>=a.d&&y<=a.u) return 1;
    return 0;
}

bool judge(ss a, ss b)
{
    if (in(a,b.l,b.u)) return 1;
    if (in(a,b.l,b.d)) return 1;
    if (in(a,b.r,b.u)) return 1;
    if (in(a,b.r,b.d)) return 1;
    return 0;
}

void dfs(int num)
{
    int value=0;
    for (int i=1; i<=m; i++)
    {
      if (p[i].flag)
      {
        for (int j=i+1; j<=m; j++)
          if (judge(p[i],p[j])) return;
      }
      value+=(p[i].r-p[i].l)*(p[i].u-p[i].d);
    }

    if (value>=ans) return;

    if (num>n){
        ans=value;
        return;
    }

    for (int i=1; i<=m; i++)
    {
        ss tmp=p[i];
        if (p[i].flag==0)
        {
            p[i].flag=1;
            p[i].l=p[i].r=mapp[num].x;
            p[i].u=p[i].d=mapp[num].y;
            dfs(num+1); p[i]=tmp;
            break;
        }
        else
        {
            p[i].r=max(p[i].r,mapp[num].x);
            p[i].l=min(p[i].l,mapp[num].x);
            p[i].u=max(p[i].u,mapp[num].y);
            p[i].d=min(p[i].d,mapp[num].y);
            dfs(num+1);
            p[i]=tmp;
        }
    }
}

int main(void)
{
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++) scanf("%d%d",&mapp[i].x,&mapp[i].y);

    dfs(1);
    printf("%d",ans);

    return 0;
}

原文地址:https://www.cnblogs.com/Chicago/p/9920720.html

时间: 2024-10-24 14:55:22

题解 P1034 【矩形覆盖】的相关文章

洛谷 P1034 矩形覆盖

P1034 矩形覆盖 题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:覆盖一个点的矩形面积为

洛谷——P1034 矩形覆盖

https://www.luogu.org/problem/show?pid=1034 题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所

P1034 矩形覆盖

题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:覆盖一个点的矩形面积为 0:覆盖平行于坐标轴

[NOIP2002] 提高组 洛谷P1034 矩形覆盖

题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:覆盖一个点的矩形面积为 0:覆盖平行于坐标轴

剑指Offer:矩形覆盖【N1】

剑指Offer:矩形覆盖[N1] 题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 题目思考 我们先把2*8的覆盖方法记为f(8),用一个2*1的小矩形去覆盖大矩形的最右边时有两种选择,横着放或者竖着放, 此时左边的空间为f(6)或f(7),那么f(8)的放置结果为f(6)[右边横着放]+f(7)[右边竖着放] 找规律 f(n)=f(n-1)+f(n-2),斐波那契数列 Java题解 public clas

BZOJ1185: [HNOI2007]最小矩形覆盖

传送门 旋转卡壳. 首先求凸包没什么好商量的. 然后有一个结论,如果存在一个最小的矩形覆盖,那么凸包里必定存在一条边和矩形的边重合. 自己yy一下就好啦,很容易想明白. 然后枚举每条边,移动另外三条边即可. 注意点积,叉积的结合运用什么的. //BZOJ 1185 //by Cydiater //2017.1.29 #include <iostream> #include <map> #include <ctime> #include <cmath> #in

NOIP2002 矩形覆盖

题四 矩形覆盖(存盘名NOIPG4) [问题描述]: 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:

NOIP2002矩形覆盖[几何DFS]

题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴.当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4.问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢.约定:覆盖一个点的矩形面积为 0:覆盖平行于坐标轴

HDU 5100 Chessboard 用 k &#215; 1 的矩形覆盖 n &#215; n 的正方形棋盘

点击打开链接 Chessboard Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 335    Accepted Submission(s): 168 Problem Description Consider the problem of tiling an n×n chessboard by polyomino pieces tha

1185: [HNOI2007]最小矩形覆盖

1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1426  Solved: 648[Submit][Status][Discuss] Description Input Output Sample Input Sample Output HINT Source 计算几何 vfleaking提供Spj #include<cstdio> #include<cmat