版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/88628566
问题描述
X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。分析:用d(i,j,cnt,max)描述在(i,j)位置拥有宝物的数量为cnt,拥有宝物的最大值为max。
#include <cstdio>
#include <cstring>
const int MOD = 1000000007, N = 50+5, K = 20, C =15, dx[2] ={0,1}, dy[2] ={1,0};
int cells[N][N], d[N][N][K][C], n, m, k;
int dp(int x, int y, int cnt,int max){ //当前位置(x,y),拥有宝物的数量cnt,拥有的宝物的最大值max;
int &ans = d[x][y][cnt][max+1]; // max有可能为-1,防止越界
if(ans != -1) return ans;
if( x == n && y == m ){
if(cnt == k) return ans = 1;
if(cnt == k-1 && max < cells[x][y]) return ans = 1;
return ans = 0;
}
long long num = 0;
for(int i = 0; i < 2; i++){
int nx = x+dx[i];
int ny = y+dy[i];
if(cells[nx][ny] != -1){
num += dp(nx,ny,cnt,max);
if(cnt < k && cells[x][y] > max) //取走宝物
num += dp( nx, ny, cnt+1, cells[x][y]);
}
}
return ans = num%MOD;
}
int main(int argc, char** argv) {
scanf("%d%d%d",&n,&m,&k);
memset(cells,-1,sizeof(cells));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d",&cells[i][j]);
memset(d, -1,sizeof(d));
int ans = dp(1,1,0,-1);
printf("%d\n",d[1][1][0][0]);
return 0;
}
输入格式
输入一行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扫描二维码关注公众号,回复: 5620977 查看本文章样例输出
2
样例输入
2 3 2
1 2 3
2 1 5样例输出
14