1. 程式人生 > 其它 >dp-數字三角形

dp-數字三角形

數字三角形問題是一個很經典的dp問題,因為這個題是在書上看到的,所以根本不知道輸入是什麼!只能通過經驗判斷輸入!!!!

注意:當前版本是我自己臆想出來的輸入。

題目描述

有一個非負整數組成的三角形,第一行只有一個數,除了最下行之外每個數的左下方和右下方各有一個數,從第一行的數開始每次可以往左下或者右下走一格,直到走到最下行,把沿途經過的數全部加起來,如何走才能得到最大和?

思考過程1

像題目中這樣說,不就是轉換成一個數組麼?

如圖所示,先轉成陣列:

注意:第\(0\)行和第\(0\)列是不需要的,因為不好計算。第\(k\)行有\(k\)個數。

像這種結構找最大或者最小值,一般就是用深搜,每條路徑都要遍歷一遍。確定了深搜之後,想一下輸入的問題,我以為這道題的輸入是給定\(n\)

,輸入這\(n\)個數。所以現在要解決的問題是\(n\)個數一共是多少層:假設\(n\)個數一共可以組成\(k\)層(假設是滿的),第\(1\)層有\(1\)數...第\(k\)層有\(k\)個數,則一定有:

\[1 + 2 + 3 + ...+k \geq n \]

左邊就是個等差數列,結果為:

\[\frac{(1+k)*k}{2} \]

展開可得:

\[k^2+k-2n \geq 0 \]

這裡求解\(k\),根據韋達定理,可知:

\[x=\frac{-b\pm \sqrt{b^2-4ac}}{2a} \]

同過這個公式可以求得\(k\)

\[k_1\geq\frac{\sqrt{1+8n}-1}{2} \\ k_2\leq\frac{-1 - \sqrt{1+8n}}{2} \]

因為\(k_2\)

一定是小於\(0\)的,所以\(k_1\)為最終答案,但此時一定是滿的,需要求解的層數進行上取整ceil()

深搜程式碼

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <deque>

using namespace std;

#define MAX_N 100
#define print(a) { \
    for (int i = 0; i < 10; i++) {\
        for (int j = 0; j < 10; j++) {\
            cout << grid[i][j] << " ";\
        }\
        cout << endl;\
    }\
}
int n, grid[MAX_N + 5][MAX_N + 5], ans = 0;
int k;

void dfs(int x, int y, int sum) {
    sum += grid[x][y];
    // cout << "(" << x << ", " << y << ")" << " " << sum << endl;
    if (x == k) {
        ans = max(sum, ans);
        return ;
    }
    if (grid[x + 1][y] >= 0) {
        dfs(x + 1, y, sum);
    }
    if (grid[x + 1][y + 1] >= 0) {
        dfs(x + 1, y + 1, sum);
    }
}

void solve() {
    memset(grid, -1, sizeof(grid));
    cin >> n;
    k = ceil((sqrt(1 + 8 * n) - 1) / 2);
    cout << "k = " << k << endl;
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= i; j++) {
            cin >> grid[i][j];
            // print(grid);
        }
    }
    dfs(1, 1, 0);
    cout << ans << endl;
}

int main() {
    solve();
    return 0;
}

未完!等回來再寫!