hdu6249

题意

\(n\)种邮票,\(m\)个邮票集合\((1\leq n,m\leq 2000)\),每个邮票集合包含一段连续编号的邮票。计算最多选择\(k(1\leq k\leq m)\)个集合所能得到的最多的邮票种类。

题解

\(n\)个点,\(m\)个区间,选择\(k\)个区间覆盖最多的点。
\(dp[i][j]\)表示选到\(i\)个点,并且选择了\(j\)个区间所覆盖的最多的点。
预处理选择第\(i\)个点时,区间向右所能延伸到的最大的点\(rmax[i]\),通过\(dp[i-1][j]+rmax[i]-i+1\)的值更新\(dp[rmax[i]][j+1]\)的值

#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int maxn=2010;
int T,k,n,m,rmax[maxn],dp[maxn][maxn];

int main(){
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%d %d %d",&n,&m,&k);
        memset(dp,0,sizeof(dp));
        memset(rmax,0,sizeof(rmax));
        for(int i=1;i<=m;i++){
            int l,r;
            scanf("%d %d",&l,&r);
            for(int j=l;j<=r;j++) rmax[j]=max(rmax[j],r);
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<k;j++){
                dp[i][j+1]=max(dp[i][j+1],dp[i-1][j+1]);
                if(rmax[i]) dp[rmax[i]][j+1]=max(dp[rmax[i]][j+1],dp[i-1][j]+rmax[i]-i+1);
            }
        }
        printf("Case #%d: %d\n",cas,dp[n][k]);
    }
}
posted @ 2021-03-31 23:51  fxq1304  阅读(35)  评论(0编辑  收藏  举报