洛谷P1854 花店橱窗布置 题解 2D/0D型动态规划

题目大意:有 \(n\) 束花及 \(m\) 个花盆,要按顺序将每一束花和花盆配对。第 \(i\) 束花和第 \(j\) 个花盆配对能够收获的价值是 \(a_{i,j}\),且要求和第 \(1 \ldots n\) 束花配对的花盆编号单调递增。求能够收获的最大价值及其中一种合法的配对方案。

解题思路:
定义状态 \(f_{i,j}\) 表示前 \(i\) 束花和前 \(j\) 个花盆(中的若干个花盆)配对的最大价值,则状态转移方程为 \(f_{i,j} = \max\{ f_{i,j-1}, f_{i-1,j-1} + a_{i,j} \}\)

上面这个就是主要思想。

然后通过递归找一下答案(见下方代码),将第 \(i\) 束花配对的花盆编号保存在 \(ans[i]\) 中即可。

示例代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int n, m, a[maxn][maxn], f[maxn][maxn], mx[maxn], ans[maxn];
void handle(int x, int y) {
    ans[x] = y;
    if (x <= 1) return;
    for (int i = x-1; i < y; i ++) {
        if (f[x-1][i] + a[x][y] == f[x][y]) {
            handle(x-1, i);
            return;
        }
    }
}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            cin >> a[i][j];
    for (int i = 1; i <= n; i ++) {
        for (int j = i; j <= m; j ++) {
            if (i == j) f[i][j] = f[i-1][j-1] + a[i][j];
            else f[i][j] = max(f[i][j-1], f[i-1][j-1] + a[i][j]);
            mx[i] = max(mx[i], f[i][j]);
        }
    }
    cout << mx[n] << endl;
    for (int i = 1; i <= m; i ++) {
        if (f[n][i] == mx[n]) {
            handle(n, i);
            break;
        }
    }
    for (int i = 1; i <= n; i ++) cout << ans[i] << " ";
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章