X 国王有一个地宫宝库,是 n×m 个格子的矩阵,每个格子放一件宝贝,每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是 k 件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 k 件宝贝。
输入格式
第一行 3 个整数,n,m,k,含义见题目描述。
接下来 n 行,每行有 m 个整数 Ci 用来描述宝库矩阵每个格子的宝贝价值。
输出格式
输出一个整数,表示正好取 k 个宝贝的行动方案数。
该数字可能很大,输出它对 1000000007 取模的结果。
数据范围
1≤n,m≤50,
1≤k≤12,
0≤Ci≤12
输入样例1:
2 2 2
1 2
2 1
输出样例1:
2
输入样例2:
2 3 2
1 2 3
2 1 5
输出样例2:
14
#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef long long LL;
const int MOD = 1000000007;
const int N = 60;
int a[N][N];
int n,m,k;
int ans;
int dp[N][N][15][15];
int dfs(int st,int ed,int maxv,int sum){
if(sum>k||st>n||ed>m)return 0;
int& v=dp[st][ed][maxv][sum];
if(v!=-1)return v;//必须要初始化为-1,因为方案数为0也得返回
if(st==n&&ed==m){
if(sum==k){
return v=1;
}
if(sum==k-1&&maxv<a[n][m]){
return v=1;
}
return v=0;
}
int t=0;
if(a[st][ed]>maxv){
t=(t+dfs(st+1,ed,a[st][ed],sum+1))%MOD;//拿
t=(t+dfs(st+1,ed,maxv,sum))%MOD;//不拿
t=(t+dfs(st,ed+1,a[st][ed],sum+1))%MOD;
t=(t+dfs(st,ed+1,maxv,sum))%MOD;
}
else{
t=(t+dfs(st+1,ed,maxv,sum))%MOD;
t=(t+dfs(st,ed+1,maxv,sum))%MOD;
}
return v=t%MOD;
}
int main()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i ++ ){
for (int j = 1; j <= m; j ++ ) {
cin >> a[i][j];
}
}
memset(dp, -1, sizeof dp);
cout<<dfs(1,1,-1,0)<<endl;
return 0;
}