zoukankan      html  css  js  c++  java
  • 题解 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;
    }
    
  • 相关阅读:
    常用正则表达式
    The Skins Factory 界面设计欣赏
    The Regulator 轻松上手
    Visual C#的Web XML编程
    业务流程不是需求
    如使用ODBC连接informix
    AJAX在信息系统中的应用研究
    浅谈几个SQL的日志概念
    量产 朗科(Netac)朗盛系列闪存盘E108 8G 手记
    【转】告诉大家他们是怎么成为富翁的
  • 原文地址:https://www.cnblogs.com/Chicago/p/9920720.html
Copyright © 2011-2022 走看看