菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
271
0

hdu6249

原创
05/13 14:22
阅读数 4269

题意

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

发表评论

0/200
271 点赞
0 评论
收藏