题意
-
在一个N * M的格子中,放有一些糖,这些糖有的会损害健康,有的对健康有益。有损害的被记为负数,有益的会记为正数。另外,对于每一个糖而言,他都比左边的糖和上面的糖更健康。
-
现在我要在在N*M这个矩阵中找到一个子矩阵,使得所有糖的有益值加起来最大。
题解
- 题目很简单,为了方便,逆序输入,使得左上角变为更优糖果
- 预处理一下,得到任意趋于左上方向的行、列之和。(简单来说就是某个点往左的和、往上的和)
- 状态转移方程:
- 还有一种不需要DP的方法,时间复杂度相同:遍历所有点, 记录从起始点(左上角)到这个位置围成的矩形的和。把所有最后遍历一边找最大值。
AC-Code
#include <bits/stdc++.h>
using namespace std;
int mp[maxn][maxn];
int dp[maxn][maxn];
int row[maxn][maxn];
int col[maxn][maxn];
int main() {
int T; cin >> T;
while (T--) {
int n, m; cin >> n >> m;
for (int i = n; i >= 1; --i) {
for (int j = m; j >= 1; --j) {
dp[i][j] = -0x3f3f3f;
cin >> mp[i][j];
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
row[i][j] = row[i][j - 1] + mp[i][j];
col[i][j] = col[i - 1][j] + mp[i][j];
}
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
dp[i][j] = max(dp[i][j], max(dp[i - 1][j] + row[i][j], dp[i][j - 1] + col[i][j]));
int ans = -0x3f3f3f;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
ans = max(ans, dp[i][j]);
cout << ans << endl;
}
return 0;
}