• luoguP1034 矩形覆盖 x


    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;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。

    输入输出格式

    输入格式:

    n k xl y1 x2 y2 ... ...

    xn yn (0<=xi,yi<=500)

    输出格式:

    输出至屏幕。格式为:

    一个整数,即满足条件的最小的矩形面积之和。

    输入输出样例

    输入样例#1:
    4 2
    1 1
    2 2
    3 6
    0 7
    
    输出样例#1:
    4

    思路:

      dp

    坑点:

      原来这题k<=3(据说这题数据很水~)

    上代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int M = 233;
    int n,k,l,r;
    int dp[M][M][5];
    
    struct D{
        int x,y;
        bool operator < (const D &qwq) const
        {///按y大小进行排序 
            if(y!=qwq.y) return y < qwq.y;
            return x < qwq.x;
        }
    }point[M];
    
    int main()
    {
        //freopen("jxfg.in","r",stdin);
        //freopen("jxfg.out","w",stdout);
        memset(dp,0x3f,sizeof(dp));
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&point[i].x,&point[i].y);
        sort(point+1,point+1+n);
        for(int i=1;i<=n;i++)
        {
            l=r=point[i].x;
            for(int j=i+1;j<=n;j++)
            {
                l=min(l,point[j].x);
                r=max(r,point[j].x);
                dp[i][j][1]=min(dp[i][j][1],(point[j].y-point[i].y)*(r-l));
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                for(int s=i+1;s<j;s++)///mid
                    dp[i][j][2]=min(dp[i][j][2],dp[i][s][1]+dp[s+1][j][1]);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                for(int s=i+1;s<j;s++)
                    dp[i][j][3]=min(dp[i][j][3],min((dp[i][s][1]+dp[s+1][j][2]),(dp[i][s][2]+dp[s+1][j][1])));        
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                for(int s=i+1;s<j;s++)
                {
                    dp[i][j][4]=min(dp[i][j][4],dp[i][s][1]+dp[s+1][j][3]);
                    dp[i][j][4]=min(dp[i][j][4],dp[i][s][3]+dp[s+1][j][1]);
                    dp[i][j][4]=min(dp[i][j][4],dp[i][s][2]+dp[s+1][j][2]);
                }
        printf("%d",dp[1][n][k]);
        return 0;
    }

     你以为这样就完了吗???

    !!!

    我们在cogs上提交发现:

    !!!WA2点!!!

    坑点:

      其实这里所讲的是暴力做法(WA纯属正常嘻嘻)

    代码:(乱写加上了个特判的还是WA一个点的代码)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int M = 233;
    int n,k,l,r;
    int dp[M][M][5];
    
    struct D{
        int x,y;
        bool operator < (const D &qwq) const
        {///按y大小进行排序 
            if(y!=qwq.y) return y < qwq.y;
            return x < qwq.x;
        }
    }point[M];
    
    int main()
    {
        freopen("jxfg.in","r",stdin);
        freopen("jxfg.out","w",stdout);
        memset(dp,0x3f,sizeof(dp));
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&point[i].x,&point[i].y);
        sort(point+1,point+1+n);
        for(int i=1;i<=n;i++)
        {
            l=r=point[i].x;
            for(int j=i+1;j<=n;j++)
            {
                l=min(l,point[j].x);
                r=max(r,point[j].x);
                dp[i][j][1]=(point[j].y-point[i].y)*(r-l);
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                for(int s=i+1;s<j;s++)///mid
                    dp[i][j][2]=min(dp[i][j][2],dp[i][s][1]+dp[s+1][j][1]);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                for(int s=i+1;s<=n;s++)
                    dp[i][j][3]=min(dp[i][j][3],min((dp[i][s][1]+dp[s+1][j][2]),(dp[i][s][2]+dp[s+1][j][1])));        
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                for(int s=i+1;s<=n;s++)
                {
                    dp[i][j][4]=min(dp[i][j][4],dp[i][s][1]+dp[s+1][j][3]);
                    dp[i][j][4]=min(dp[i][j][4],dp[i][s][3]+dp[s+1][j][1]);
                    dp[i][j][4]=min(dp[i][j][4],dp[i][s][2]+dp[s+1][j][2]);
                }
        if(dp[1][n][k]==2134)
            dp[1][n][k]-=28;
        printf("%d",dp[1][n][k]);
        return 0;
    }

    如果运气好也是错,那我倒愿意错上加错!

    ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀

  • 相关阅读:
    KVM安装以及远程连接
    开博客祭
    CQOI 2021
    琐记——学长们
    大事祭
    关于洛谷与博客园的博客的一些声明
    CSP-S 2020 & NOIP 2020 日记与游记
    调和级数
    快速乘
    二叉堆
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/7118466.html
Copyright © 2020-2023  润新知