题目传送门:洛谷1437
决定要养成随手记录做过的题目的好习惯呀~
这道题目乍看起来和数字三角形有一点像,但是仔细分析就会发现,因为选定一个数所需要的条件和另一个数所需要的条件会有重复的部分,所以状态不好转移,也会产生后效性。
但是,通过将所有的砖块左移,我们可以发现(i, j)砖块所需要的条件就是(i-1, j) (i-1, j+1)这两块砖均被敲掉。
所以dp方程顺理成章:i,j,k分别表示从第i列j行开始算起,取k个数所能获得的最大价值和。
dp[i][j][s] = max(dp[i+1][s][k-j] +sum[第i列前j个数之和])(s>=j+1,<=该行最大数目)
#include <bits/stdc++.h> using namespace std; #define maxn 55 #define maxm 1500 int n, m, ans, sum[maxn][maxn], dp[maxn][maxn][maxm]; int read() { int x = 0; char c; c = getchar(); while(c < ‘0‘ || c > ‘9‘) c = getchar(); while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar(); return x; } int main() { n = read(), m = read(); for(int i = 1; i <= n; i ++) for(int j = 1; j <= n - i + 1; j ++) sum[j][i] += read() + sum[j][i - 1]; for(int i = n; i >= 1; i --) { int len = n - i + 1; for(int j = 0; j <= len; j ++) for(int s = m; s >= max(0, 2 * j - 1); s --) for(int k = j - 1; k <= len - 1; k ++) { dp[i][j][s] = max(dp[i + 1][k][s - j] + sum[i][j], dp[i][j][s]); ans = max(ans, dp[i][j][s]); } } printf("%d\n", ans); return 0; }