出题人:DS课程组
单位:临沂大学
小明有一张藏宝图,上面有n*m个房间,每个房间里面都有一个有一定价值的宝物,小明只能从左上角的房间进入,且每次只能向右或向下行走,最终只能从最右下的房间出来。经过某个房间时,如果该房间中的宝物价值比小明手中任何宝物价值都大,小明就可以拿走它,当然,也可以不拿。当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝物就可以送给小明。请你帮小明算一算,他有多少种不同的行动方案能获得这k件宝贝。
输入格式
输入第一行3个整数n,m,k(1<=n,m<=50,1<=k<=12),其间空格分割。
接下来有n行数据,每行有m个整数Vi(0<=Vi<=12),代表这个房间里的宝物的价值。
输出格式
要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对1000000007取模的结果。
输入样例
2 2 2
1 2
2 1
输出样例
2
输入样例2
2 3 2
1 2 3
2 1 5
输出样例2
14
思路
dfs,注意题目数据,需要取模,因此普通的dfs肯定会超时,需要用到记忆化搜索,具体看代码
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
int val[51][51];
int n, m, k;
int dp[51][51][13][13];
int dfs(int x, int y, int ma, int sum)
{
if(x > n || y > m || sum > k)
return 0;
if(dp[x][y][ma][sum] != -1)
return dp[x][y][ma][sum];
int temp = val[x][y];
int res = 0;
if(x == n && y == m){
if(sum == k || (sum == k-1 && temp > ma))
return 1;
else
return 0;
}
if(temp > ma){
res += dfs(x, y+1, temp, sum+1);
res %= mod;
res += dfs(x+1, y, temp, sum+1);
res %= mod;
}
res += dfs(x, y+1, ma, sum);
res %= mod;
res += dfs(x+1, y, ma, sum);
dp[x][y][ma][sum] = res%mod;
return res%mod;
}
int main()
{
cin>>n>>m>>k;
memset(dp, -1, sizeof(dp));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin>>val[i][j];
cout<<dfs(1, 1, -1, 0)<<endl;
}