题目链接:
http://lx.lanqiao.cn/problem.page?gpid=T120
思路:
1.记
d
p
[
i
]
[
j
]
[
a
]
[
b
]
dp[i][j][a][b]
dp[i][j][a][b]为走到坐标为
(
i
,
j
)
(i,j)
(i,j)位置后,手上有
a
a
a件物品且所有物品中最大值为
b
b
b的方案数;
2.假设我们现在从
(
a
,
b
)
(a,b)
(a,b)走到
(
x
,
y
)
(x,y)
(x,y)(这两个位置相邻),记
v
[
i
]
[
j
]
v[i][j]
v[i][j]是处在坐标为
(
i
,
j
)
(i,j)
(i,j)的物品的价值,那么到
(
x
,
y
)
(x,y)
(x,y)可以选择不取该位置的物品,如果该位置物品大于
(
a
,
b
)
(a,b)
(a,b)处物品的最大值、那么也可以选择取此处的物品;
复杂度
O
(
n
m
k
C
)
O(nmkC)
O(nmkC)
代码:
#include<bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int n, m, k, v[55][55];
int dp[55][55][15][15];
#define f(a, b) a = (a + b) % mod;
inline void check(int a, int b, int & x, int & y) {
if(a <= 0 || b <= 0) return;
for(int i = 0; i <= k; i++) {
for(int j = 0; j <= 13; j++) {
f(dp[x][y][i][j], dp[a][b][i][j]);
if(v[x][y] > j) f(dp[x][y][i + 1][v[x][y]], dp[a][b][i][j]);
}
}
}
int main() {
#ifdef MyTest
freopen("Sakura.txt", "r", stdin);
#endif
scanf("%d %d %d", &n, &m, &k);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
scanf("%d", &v[i][j]);
++v[i][j];
}
}
dp[1][1][0][0] = 1;
dp[1][1][1][v[1][1]] = 1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
check(i - 1, j, i, j);
check(i, j - 1, i, j);
}
}
int ans = 0;
for(int i = 1; i <= 13; i++) f(ans, dp[n][m][k][i]);
printf("%d", ans);
return 0;
}