题目描述
https://www.luogu.com.cn/problem/P4138
Solution
我们令 $f[i][j]$ 表示前 $i$ 个挂饰,有 $j$ 个挂钩的最大收益
由于挂钩的数量影响下一个挂饰能否被选择,而最外层又是循环挂饰,所以必须将挂饰按照挂钩数量从大到小排序
另外我们不需要存储超过 $n$ 个挂钩,所以我们将定义改为有大于等于 $j$ 个挂钩
时间复杂度 $O(n^2)$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <iostream> #include <cstdio> #include <algorithm> #define maxn 2010 #define INF 1000000000 #define cn const node using namespace std;
int n;
int f[maxn][maxn];
struct node { int x, y;
friend bool operator < (cn &u, cn &v) { return u.x > v.x; } } a[maxn];
int main() { cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i].x >> a[i].y; sort(a + 1, a + n + 1); for (int i = 0; i < maxn; ++i) for (int j = 0; j < maxn; ++j) f[i][j] = -INF; f[0][1] = 0; for (int i = 1; i <= n; ++i) for (int j = 0; j <= n; ++j) f[i][j] = max(f[i - 1][j], f[i - 1][max(j - a[i].x, 0) + 1] + a[i].y); int ans = 0; for (int i = 0; i <= n; ++i) ans = max(ans, f[n][i]); cout << ans << endl; return 0; }
|