HDU 2571 命运(简单dp)

 

传送门

真是刷越多题,越容易满足。算是一道很简单的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;
}
View Code

 

posted @ 2019-03-14 00:41  Mrzdtz220  阅读(196)  评论(0编辑  收藏  举报