洛谷P1854 花店櫥窗佈置 題解 2D/0D型動態規劃
阿新 • • 發佈:2021-01-19
題目大意:有 \(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\)
示例程式碼:
#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; }