【動的計画法問題4】ギフトの最大値&&降下経路の最小和

贈り物の最大の価値

m*n チェス盤の各マス目にギフトが配置され、各ギフトには特定の値 (0 より大きい値) があります。ボードの左上隅から開始してグリッド内のギフトを取得し、ボードの右下隅に到達するまで一度に 1 つのグリッドを右または下に移動できます。チェス盤とそこに置かれたギフトの価値が与えられた場合、あなたが得ることができるギフトの最大価値を計算しますか?

リンク:ソードポイントオファー 47. 贈り物の最大の価値

例 1:
入力:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
出力: 12
説明: パス 1→3→5→2→1 が最も多くの値を取得できます自分の贈り物

1. ステータス表現

この「パスの種類」の問題については、ステータス表現には通常、次の 2 つの形式があります。

  1. i. 位置 [i, j] から開始して...;
  2. ii. 開始位置から開始して [i, j] 位置に到着します...;

ここでは、状態表現を定義する 2 番目の方法を選択します。dp
[i][j] は、位置 [i, j]、現時点での最大値に到達することを意味します。

2. 状態遷移方程式

dp[i][j] の場合、位置 [i, j] に到達するには 2 つの方法があることがわかります。

  1. i. 位置[i, j]の上の位置[i - 1, j]から一段下に進み、位置[i, j]に到達したときに獲得できるギフトの値はdp[i - 1]です][ j] + グリッド[i][j];
  2. ii. 位置[i, j]の左側の位置[i, j - 1]から右に一歩進み、このとき位置[i]に到達したときに獲得できるギフトの価値は, j] は dp[i][j - 1 ] + グリッド[i][j] です

必要なのは最大値であるため、状態遷移方程式は次のようになります。

dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + grid[i][j] 

3. 初期化

いくつかの境界条件を解決するために補助ノードを追加することができますが、
この問題では「行の追加」と「列の追加」後の値はすべて 0 になります。

4. フォームの記入順序
「状態移行プロセス」では、フォームの記入順序は「各行を上から下に記入する」、「各行を左から右に記入する」となっています。

5. 戻り値
dp[m][n]の値を返します。

コード:

 int maxValue(vector<vector<int>>& grid) {
    
    
        int n=grid.size();
        int m=grid[0].size();
        vector<vector<int>> dp(n+1,vector<int>(m+1));

        for(int i=1;i<=n;i++)
        {
    
    
            for(int j=1;j<=m;j++)
            {
    
    
                dp[i][j]=max(dp[i][j-1],dp[i-1][j])+grid[i-1][j-1];
            }
        }
        return dp[n][m];
    }

ここに画像の説明を挿入します

931. 下降経路の最小合計

nxn の正方整数配列行列が与えられた場合、行列を通る降順パスの最小合計を見つけて返してください。

降順パスは、最初の行の任意の要素から開始し、各行から 1 つの要素を選択できます。次の行で選択されている要素は、現在の行で選択されている要素 (つまり、真下または左または右の斜めの最初の要素) から最大 1 列離れています。具体的には、位置 (row,col) の次の要素は (row + 1,col - 1)、(row + 1,col)、または (row + 1,col + 1) である必要があります。

リンク:降順パスの最小合計

ここに画像の説明を挿入します

入力: 行列 = [[2,1,3],[6,5,4],[7,8,9]]
出力: 13
説明: 図に示すように、合計が最小となる 2 つの下降パスがあります。

1. ステータス表現

この「パスの種類」の問題については、ステータス表現には通常、次の 2 つの形式があります。

  1. i. 位置 [i, j] から開始して...;
  2. ii. 開始位置から開始して [i, j] 位置に到着します...;

ここでも、状態表現を定義する 2 番目の方法を選択します。dp
[i][j] は、すべての下降パスの最小合計である位置 [i, j] に到達することを意味します。

2. 状態遷移方程式

dp[i][j] の場合、位置 [i, j] に到達するには 3 つの方法があることがわかります。

  1. i. [i - 1, j] の真上の位置から [i, j] の位置に移動します。
  2. ii. 左上の位置 [i - 1, j - 1] から [i, j] の位置に移動します。
  3. iii. 右上の位置 [i - 1, j + 1] から位置 [i, j] に移動します。

必要なのは 3 つの状況における「最小値」であり、[i, j] の位置に行列の値を加算します。
それから

dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j +1])) + matrix[i][j] 

3. 初期化

いくつかの境界条件を解決するには、補助ノードを追加します。
この問題では、「1 つの行を追加」し、「2 つの列を追加」する必要があります。すべての位置が無限大に初期化され、最初の行が 0 に初期化されます。

4. フォームへの入力順序
フォームへの入力順序は上から下へ

5. 戻り値
ここでは dp[m][n] の値は返されないことに注意してください。
タイトルには「最後の行に達する限り」必要があるため、「dp テーブルの最後の行の最小値」を返す必要があります。

コード:

    int minFallingPathSum(vector<vector<int>>& matrix) {
    
    
        int m=matrix.size();
        int n=matrix[0].size();
        vector<vector<int>> dp(m+1,vector<int> (n+2,INT_MAX));

        for(int i=0;i<n+2;i++) dp[0][i]=0;//初始化第一行的值
        int count=0;
        
        for(int i=1;i<=m;i++)
        {
    
    
            for(int j=1;j<=n;j++)
            {
    
    
                dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i-1][j+1]))+matrix[i-1][j-1];
            }

        }

        int ret=INT_MAX;//返回值
        for(int i=1;i<=n;i++) ret=min(ret,dp[n][i]);
        return ret;
    }

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/m0_64579278/article/details/132112128