zoukankan      html  css  js  c++  java
  • 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;
    }

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

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

  • 相关阅读:
    【今日CV 视觉论文速览】 19 Nov 2018
    【numpy求和】numpy.sum()求和
    【今日CV 视觉论文速览】16 Nov 2018
    【今日CV 视觉论文速览】15 Nov 2018
    poj 2454 Jersey Politics 随机化
    poj 3318 Matrix Multiplication 随机化算法
    hdu 3400 Line belt 三分法
    poj 3301 Texas Trip 三分法
    poj 2976 Dropping tests 0/1分数规划
    poj 3440 Coin Toss 概率问题
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/7118466.html
Copyright © 2011-2022 走看看