數塔 HDU - 2084 (簡單DP)

題目鏈接:https://vjudge.net/problem/HDU-2084

思路1:從上往下遞推

dp[i][j]表示第i層第j個節點經過結點的數字之和的最大的值。

狀態轉移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+a[i][j]。對j==1與j==i進行特判

代碼:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
int a[maxn][maxn], dp[maxn][maxn];

int main() {
    int C, N;
    scanf("%d", &C);
    while (C--) {
        scanf("%d", &N);
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= i; j++) {
                scanf("%d", &a[i][j]);
            }
        }
        memset(dp,0,sizeof(dp));
        dp[1][1] = a[1][1];
        for (int i = 2; i <= N; i++) {
            for (int j = 1; j <= i; j++) {
                if (j == 1) dp[i][j] = dp[i - 1][1] + a[i][j];
                else if (j == i) dp[i][j] = dp[i - 1][j-1] + a[i][j];
                else {
                    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + a[i][j];
                }
            }
        }
        int ans = -1;
        for (int i = 1; i <= N; i++) {
            ans = max(ans, dp[N][i]);
        }
        cout << ans << endl;
    }
    return 0;
}

思路2:從下往上遞推

討論:我們要得到“經過結點的最大數字之和”,路徑的首與尾是確定的,首是第一層的頭節點,尾一定是在第n層節點。

我們這裏設定dp[0][0]爲我們要求的答案,也即從尾出發走到頭。

狀態轉移方程:dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+dp[i][j];

代碼:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
int dp[maxn][maxn];
int C, N;
int main() {
    scanf("%d", &C);
    while (C--) {
        scanf("%d", &N);
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= i; j++) {
                scanf("%d", &dp[i][j]);
            }
        }
        for (int i = N - 1; i >= 1; i--) {
            for (int j = 1; j <= i; j++) {
                dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + dp[i][j];
            }
        }
        cout << dp[1][1] << endl;
    }
    return 0;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章