洛谷1034 NOIP2002 矩形覆盖

问题描述

在平面上有 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。各个矩形必须完全分开(边线与顶点也都不能重合)。

从黄学长那里看到这道题说是k<=4 实际上 k最大是3

所以简单的区间dp就可以过 

#include<bits/stdc++.h>
using namespace std;
int f[55][55][5];
struct node{
    int x,y;
}a[55];
int n,k,l,r;
bool cmp(node a,node b){
    if(a.y==b.y)return a.x<b.x;
    return a.y<b.y;
}
int main(){
    memset(f,127/3,sizeof f);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i].x,&a[i].y);
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        l=r=a[i].x;
        for(int j=i;j<=n;j++){
            l=min(l,a[j].x);r=max(r,a[j].x);
            f[i][j][1]=(a[j].y-a[i].y)*(r-l);
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            for(int q=i;q<j;q++){
                f[i][j][2]=min(f[i][j][2],f[i][q][1]+f[q+1][j][1]);
            }
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            for(int q=i;q<j;q++){
                f[i][j][3]=min(f[i][j][3],f[i][q][1]+f[q+1][j][2]);
                f[i][j][3]=min(f[i][j][3],f[i][q][2]+f[q+1][j][1]);
            }
    printf("%d",f[1][n][k]);
    return 0;
}
原文地址:https://www.cnblogs.com/Elfish/p/7694951.html