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]);
}
}