1212. 地宮取寶

無敵少年小旋風發表於2020-12-07

AcWing網站原題通道

文章目錄

1212. 地宮取寶

在這裡插入圖片描述

題意:
給定一個迷宮,從左上角走到右下角,我們最多可以取k個寶貝,並且我們能取的寶貝的價值必須大於我們已經取到的寶貝的最大價值,問共有多少種走法。

分析:
根據題目,知道需要使用動態規劃來做,那麼就先進行動態規劃的分析。
使用閆氏DP分析法:
在這裡插入圖片描述
只分析最後一步,可以從上向下,可以從左向右,分為兩種,而對於每一種行走的方式,又可以取或者不取,取的話還需要符合當前的寶貝的價值大於已經擁有的寶貝的最大的價值。
所以動態規劃陣列開4維:f[n][m][k][v]:表示從起點到[n][m]時,選取k個物品,最大的物品是v的合法的方案

#include <iostream>
#include <cstring>

using namespace std;

const int N = 55 , MOD = 1000000007;

int n , m , k; 
int w[N][N];
int f[N][N][13][14];

int main()
{
    cin >> n >> m >> k;
    
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
        {
            cin >> w[i][j];
            w[i][j] ++;
        }
        
    f[1][1][0][0] = 1; // 不選第[1,1]個物品
    f[1][1][1][w[1][1]] = 1; // 選第[1,1]個物品
    
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(i == 1 && j == 1) continue;
            // 遍歷選取u個物品
            for(int u = 0; u <= k; u++)
            {
                // 遍歷選取u個物品的最後一個物品的最大的價值
                // 我們將價值+1,所以價值從1~13,因為也有不選物品的情況價值為0,所以0~13
                for(int v = 0; v <= 13; v++)
                {
                    int& val = f[i][j][u][v];
                    // 1.最後一步從上邊下來且不選取當前物品
                    val = (val + f[i-1][j][u][v]) % MOD;
                    // 2.最後一步從左邊過來且不選取當前物品
                    val = (val + f[i][j-1][u][v]) % MOD;
                    
                    // 如果v==w[i][j]我們可以選擇當前物品
                    if(u > 0 && v == w[i][j])
                    {
                        // 我們選取當前物品,那麼之前的物品的價值一定小於當前物品
                        for(int c = 0; c < v; c++)
                        {
                            // 3.最後一步從上邊下來且選取當前物品
                            val = (val + f[i-1][j][u-1][c]) % MOD;
                            // 4.最後一步從左邊過來且選取當前物品
                            val = (val + f[i][j-1][u-1][c]) % MOD;
                        }
                    }
                }
            }
        }
    }
    
    int res = 0;
    for(int i = 1; i <= 13; i++) res = (res + f[n][m][k][i]) % MOD;
    cout << res << endl;
    
    return 0;
}

相關文章