题目链接 HDU 6249
题意 给定$m$个区间,在这些区间中选出不超过$k$个,求被覆盖的点的数量的最大值。
设$f[i][j]$表示选到第$i$个点并选了$j$个区间的时候能得到的最大答案。
处理到第$i$个点的时候观察所有覆盖$i+1$这个点的线段,找到延伸到最右端的这条线段。
假设该线段延伸到$r$,那么更新$f[r][j + 1]$。
最后枚举答案即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 2010; int T; int ca = 0; int f[N][N]; int l[N], r[N]; int n, m, k; int ans; int main(){ scanf("%d", &T); while (T--){ scanf("%d%d%d", &n, &m, &k); rep(i, 1, m) scanf("%d%d", l + i, r + i); rep(i, 0, n + 1) rep(j, 0, m + 1) f[i][j] = 0; f[0][0] = 0; rep(i, 0, n - 1){ int rr = 0; rep(j, 1, m){ if (l[j] <= i + 1) rr = max(rr, r[j]); } rep(j, 0, k) f[i + 1][j] = max(f[i + 1][j], f[i][j]); if (rr == 0) continue; rep(j, 0, k - 1) f[rr][j + 1] = max(f[rr][j + 1], f[i][j] + rr - i); } ans = 0; rep(i, 1, n) rep(j, 0, k) ans = max(ans, f[i][j]); printf("Case #%d: %d\n", ++ca, ans); } return 0; }