历届试题 地宫取宝

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/88628566

题目链接 

问题描述

  X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。

  地宫的入口在左上角,出口在右下角。

  小明被带到地宫的入口,国王要求他只能向右或向下行走。

  走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
  当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
  请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。

分析:用d(i,j,cnt,max)描述在(i,j)位置拥有宝物的数量为cnt,拥有宝物的最大值为max。

状态描述原文链接:http://www.mamicode.com/info-detail-535827.html

#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

猜你喜欢

转载自blog.csdn.net/qq_42835910/article/details/88628566