1. 程式人生 > 實用技巧 >1212. 地宮取寶

1212. 地宮取寶

狀態表示:f(i, j, k, c) 表示走到(i, j)格子,已經取到k件寶物,並且最後一件寶物的價值為c的所有取法的集合,儲存數量屬性

狀態計算:集合劃分


\(f(i, j, k, c)=\) 集合中所有的數量加起來

通過集合分析得到狀態轉移方程:
\( f(i, j, k, c) = f(i-1,j,k,c) + f(i,j-1,k,c) + \delta ,\\ 其中 \delta = f(i,j-1,k-1,c') + f(i-1,j,k-1,c'),(k>0,c'=0,1,2,...,c-1)\\ f(1, 1,1,w[1][1]) = 1,f(1,1,0,0) = 1 \)

#include<iostream>
using namespace std;

const int N = 60, MOD = 1000000007;

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


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][1][w[1][1]] = 1;
    f[1][1][0][0] = 1;
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++){
            if(i == 1 && j == 1) continue;
            for(int k = 0; k <= 12; k ++) // 此處可以只迴圈到輸入的k為止
                for(int c = 0; c <= 13; c ++){
                    int &val = f[i][j][k][c];
                    val = (val + f[i][j - 1][k][c]) % MOD;
                    val = (val + f[i - 1][j][k][c]) % MOD; 
                    if(k > 0 && w[i][j] == c)
                        for(int _c = 0; _c < c; _c ++){
                            val = (val + f[i][j - 1][k - 1][_c]) % MOD;
                            val = (val + f[i - 1][j][k - 1][_c]) % MOD;
                        }
                            
                }
        }
        
    int res = 0;
    for(int i = 1; i <= 13; i ++) res = (res + f[n][m][k][i]) % MOD; //統計符合條件的答案
    
    cout << res;
}