真是刷越多题,越容易满足。算是一道很简单的DP了。终于可以自己写出来了。
二维矩阵每个点都有一个幸运值,要求从左上走到右下最多能积累多少幸运值。
重点就是左上右下必须都踩到。
dp[i][j] = map[i][j] + max(dp[i-1][j], dp[i][j-1], dp[i][k]) k是j的约数
很简单明了 就是一个细节 当map[1][1]是负数的时候 按这个关系式 dp[1][2]是不会选择从(1,1)出发的
那么就可以把map[1][1]的值加到map[n][m]上 把map[1][1]设为0 这样推就没有问题了
我只用了一个dp数组 能懒则懒(
代码如下
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 25; int dp[maxn][maxn * 100]; int main() { int T; scanf("%d", &T); while (T--) { int n, m; scanf("%d%d", &n, &m); memset(dp, 0, sizeof(dp)); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { scanf("%d", &dp[i][j]); } } dp[n][m] += dp[1][1]; dp[1][1] = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { int temp = 0; for (int k = j; k >= 2; k--) { if (j % k == 0) temp = max(temp, dp[i][j/k]); } dp[i][j] += max(dp[i][j-1], max(dp[i-1][j], temp)); } } printf("%d\n", dp[n][m]); // for (int i = 1; i <= n; i++) { // for (int j = 1; j <= m; j++) { // printf("%d ", dp[i][j]); // } // puts(""); // } } return 0; }