题意:(摘自刘汝佳的训练指南)给出n*m网格中每个格子的A矿和B矿的数量,A矿必须由右向左运输,B矿必须由下向上运输,管子不能拐弯或间断(即往上和往左的路线不能有交集)。要求使收集到的A,B矿总量尽量大。
思路:考虑到管子不能转弯和间断,可以设dp[i][j]为以i,j为左下角的最大矿总量.
开两个辅助数组A[i][j]为在i,j位置的时候建A管子的时候从i,j到i, 1的总和, B[i][j]为在i,j位置的时候建B管子的时候从i,j到1, j的总和.
这两个数组可以递推计算:A[i][j] = A[i][j - 1] + mat_a[i][j], B[i][j] = B[i - 1][j] + mat_b[i][j].
那么就可以得到一个转移方程:dp[i][j] = max(dp[i - 1][j] + A[i][j], dp[i][j - 1] + B[i][j]).
这题还是比较简单的.
#include <cstdio>
#include <algorithm>
#include <cctype>
using namespace std;
const int MAX = 502;
int mat_a[MAX][MAX], mat_b[MAX][MAX];
int A[MAX][MAX], B[MAX][MAX], dp[MAX][MAX];
int main(int argc, char const *argv[]){
int n, m;
while(scanf("%d%d", &n, &m)){
if(!n && !m)break;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
scanf("%d", &mat_a[i][j]);
}
}
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
scanf("%d", &mat_b[i][j]);
}
}
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
A[i][j] = A[i][j - 1] + mat_a[i][j];
}
}
for(int i = 1; i <= m; ++i){
for(int j = 1; j <= n; ++j){
B[i][j] = B[i - 1][j] + mat_b[i][j];
}
}
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
dp[i][j] = max(dp[i - 1][j] + A[i][j], dp[i][j - 1] + B[i][j]);
}
}
printf("%d\n", dp[n][m]);
}
return 0;
}