题意
有(n)种邮票,(m)个邮票集合((1leq n,mleq 2000)),每个邮票集合包含一段连续编号的邮票。计算最多选择(k(1leq kleq 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
",cas,dp[n][k]);
}
}