//卡壳点:m写成了n,这也是高频卡壳错误,需要优先检查
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int mod = 1000000007;int n,m,k; int f[55][55][15][15]; int w[55][55]; 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; f[1][1][1][w[1][1]] = 1; for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++){//卡壳点:m写成了n这也是高频卡壳错误 if(i == 1 && j == 1)continue; for(int a = 0;a <= k;a++){ for(int b = 0;b <= 13;b++){ int &val = f[i][j][a][b] ; val = (val + f[i][j-1][a][b]) % mod; val = (val + f[i-1][j][a][b]) % mod; if(a > 0 && b < w[i][j]){ int &vall = f[i][j][a][w[i][j]]; vall = (vall + f[i][j-1][a-1][b]) % mod; vall = (vall + f[i-1][j][a-1][b]) % mod; } } } } } int res = 0; for (int i = 0; i <= 13; i ++ ) res = (res + f[n][m][k][i]) % mod; cout << res << endl; }
思路
// // 数据范围
// 1≤n,m≤50
// ,
// 1≤k≤12
// ,
// 0≤Ci≤12
// // 范围小,不用在意
// // 他有多少种不同的行动方案能获得这 k
// // 件宝贝。
// // 切入点 求满足条件的方案数量 dp,枚举,dfs
// dp
// 状态表示 集合 坐标,最大价值,数量 ,四维数组表示f[i][j][k][w] 走到i,j时k件物品,最大价值为w的方案数
// 需要用0作第四维下标来表示还没有选,因此w读入时要++
// 属性 数量
// 状态计算 集合划分 最后一个不一样的点 f[i][j][k][w];
// 拿I,J f[i-1][j][k-1][0~w[i][j]-1];
// f[i][j-1][k-1][0~w[i][j]-1];
// 不拿i,j f[i-1][j][k][0~13];
// f[i][j-1][k][0~13];
// 所有方案相加得f[i][j],两两相加之后取模
// // 输出f[i][j][k][0~13]
// 边界初始化f[1][1][0][0] = 1;
// f[1][1][1][w[1][1]] = 1;