1. 程式人生 > 其它 >AcWing1015_摘花生

AcWing1015_摘花生

技術標籤:AcWing演算法動態規劃

AcWing1015.摘花生

題目連結:AcWing1015.摘花生

1. 題目描述

Hello Kitty想摘點花生送給她喜歡的米老鼠。

她來到一片有網格狀道路的矩形花生地(如下圖),從西北角進去,東南角出來。

地裡每個道路的交叉點上都有種著一株花生苗,上面有若干顆花生,經過一株花生苗就能摘走該它上面所有的花生。

Hello Kitty只能向東或向南走,不能向西或向北走。

問Hello Kitty最多能夠摘到多少顆花生。

AcWing1015.摘花生

輸入格式
第一行是一個整數 T T T

,代表一共有多少組資料。
接下來是 T T T組資料。
每組資料的第一行是兩個整數,分別代表花生苗的行數 R R R和列數 C C C
每組資料的接下來 R R R行資料,從北向南依次描述每行花生苗的情況。每行資料有 C C C個整數,按從西向東的順序描述了該行每株花生苗上的花生數目 M M M

輸出格式
對每組輸入資料,輸出一行,內容為Hello Kitty能摘到得最多的花生顆數。

資料範圍
1 ≤ T ≤ 100 , 1 \leq T \leq 100, 1T100,
1 ≤ R , C ≤ 100 , 1 \leq R,C \leq 100, 1R,C100,
0 ≤ M ≤ 1000 0 \leq M \leq 1000

0M1000

輸入樣例:

2
2 2
1 1
3 4
2 3
2 3 4
1 6 5

輸出樣例:

8
16

2. 解題思路

本題和AcWing898. 數字三角形的分析思路是一樣的,只是在走法上有略微的不同,本題的走法是向右和向下走,即由 ( i − 1 , j ) → ( i , j ) (i - 1, j) \rightarrow (i, j) (i1,j)(i,j) f ( i , j − 1 ) → f ( i , j ) f(i, j - 1) \rightarrow f(i, j) f(i,j1)f(i,j)
D P { 狀 態 表 示 f ( i , j ) { 集 合 : 所 有 從 ( 1 , 1 ) 走 到 ( i , j ) 走 法 的 集 合 屬 性 : m a x ( 路 徑 上 權 值 的 最 大 值 ) 狀 態 計 算 : 對 於 ( i , j ) 可 以 從 ( i − 1 , j ) 和 ( i , j − 1 ) 轉 移 過 來 , 即 ( 1 , 1 ) → ( i − 1 , j ) → ( i , j ) , 前 一 步 部 分 正 好 表 示 的 是 f ( i − 1 , j ) , 同 理 ( i , j − 1 ) 這 個 點 可 以 表 示 為 f ( i , j − 1 ) 。 兩 者 取 一 個 m a x , 再 加 上 w ( i , j ) 的 值 即 可 得 到 f ( i , j ) 的 結 果 。 DP\begin{cases} 狀態表示 f(i,j) \begin{cases} 集合:所有從(1, 1)走到(i, j)走法的集合 \\ \\ 屬性:max (路徑上權值的最大值) \end{cases}\\ \\ 狀態計算: 對於(i, j)可以從(i - 1, j)和(i, j - 1)轉移過來,\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 即(1, 1) \rightarrow (i - 1, j) \rightarrow (i, j), 前一步部分正好表示的是f(i - 1, j), \\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 同理(i, j - 1)這個點可以表示為f(i, j - 1)。\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 兩者取一個max,再加上w(i, j)的值即可得到f(i, j)的結果。 \end{cases}

DPf(i,j)(1,1)(i,j)max():(i,j)(i1,j)(i,j1)(1,1)(i1,j)(i,j),f(i1,j),(i,j1)f(i,j1)maxw(i,j)f(i,j)

最後答案是 f ( n , m ) f(n, m) f(n,m)

3. 程式碼實現

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

int n, m, T;
int w[N][N];
int f[N][N];

int main()
{
    scanf("%d", &T);
    while (T --)
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= m; j ++ )
                cin >> w[i][j];
        
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= m; j ++ )
                f[i][j] = max(f[i - 1][j], f[i][j - 1]) + w[i][j];
            
        printf("%d\n", f[n][m]);
    }
    return 0;
}

4. 注意事項

本題的初始化和數字三角形的區別是:雖然有非法狀態,但非法狀態在轉移時不會影響到正常狀態的更新,所以不用初始化。