问题描述 X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。 地宫的入口在左上角,出口在右下角。 小明被带到地宫的入口,国王要求他只能向右或向下行走。 走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。 当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。 请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。 输入格式 输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12) 接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值 输出格式 要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。 样例输入 2 2 2 1 2 2 1 样例输出 2 样例输入 2 3 2 1 2 3 2 1 5 样例输出 14
dp,记忆化搜索可以免除一些不必要的计算。记录当前坐标和当前宝物数量还有当前持有最大价值。每次更新前要判断下一步是否满足条件
状态转移方程:
dp(i, j, k, v) = max (
dp(i+1, j, k, v) + dp(i, j+1, k, v) (G(i, j) <= v),
dp(i+1, j, k+1, G(i, j)) + dp(i, j+1, k+1, G(i, j)) + dp(i+1, j, k, v) + dp(i, j+1, k, v) (G(i, j) > v)
)
代码如下:
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 typedef long long ll; 23 const ll maxn = 55; 24 const ll mod = 1000000007; 25 int n, m, kk; 26 ll G[maxn][maxn]; 27 ll dp[maxn][maxn][15][15]; 28 29 ll dfs(ll i, ll j, ll k, ll v) { 30 if(dp[i][j][k][v+1] != -1) return dp[i][j][k][v+1]; 31 if(i == n - 1 && j == m - 1) { 32 if(k == kk) return dp[n-1][m-1][k][v+1] = 1; 33 else if(k == kk - 1 && G[n-1][m-1] > v) return dp[n-1][m-1][k][v+1] = 1; 34 else return dp[n-1][m-1][k][v+1] = 0; 35 } 36 ll s = 0; 37 if(G[i][j] > v) { 38 if(i + 1 < n) s = ((s + dfs(i+1, j, k+1, G[i][j])) % mod + dfs(i+1, j, k, v) % mod) % mod; 39 if(j + 1 < m) s = ((s + dfs(i, j+1, k+1, G[i][j])) % mod + dfs(i, j+1, k, v) % mod) % mod; 40 } 41 else { 42 if(i + 1 < n) s = (s + dfs(i+1, j, k, v) % mod) % mod; 43 if(j + 1 < m) s = (s + dfs(i, j+1, k, v) % mod) % mod; 44 } 45 return dp[i][j][k][v+1] = s; 46 } 47 48 int main() { 49 // freopen("in", "r", stdin); 50 while(~scanf("%d %d %d", &n, &m, &kk)) { 51 memset(dp, -1, sizeof(dp)); 52 for(ll i = 0; i < n; i++) { 53 for(ll j = 0; j < m; j++) { 54 scanf("%d", &G[i][j]); 55 } 56 } 57 dfs(0, 0, 0, -1); 58 printf("%I64d ", dp[0][0][0][0]); 59 } 60 return 0; 61 }