2014蓝桥杯:地宫取宝

八、题目;地宫取宝
问题描述
  X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。

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

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

走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
输入格式
  输入一行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
样例输出
2
样例输入
2 3 2
1 2 3
2 1 5
样例输出
14


1.分析思路:
有三个条件:

  • 入口在左上角,出口在右下角,只能向下或者向右走一个
  • 格子中的宝贝价值比手中任意宝贝价值都大,小明可以拿起它,也可以不拿
  • 走到出口时,手中的宝贝恰好是k件
    在这里插入图片描述
    在这里插入图片描述

刚开始使用深度搜索发现,方案数会变得很复杂
题目的意思很简单,就是用深搜的方式来找出到底有多少路径,但是开始的时候虽然一眼就认定了是深度搜索,但是还真的不知道怎么搜,因为碰到不能捡的物品就不知道该怎么处理了,每一个路口会遇到四种不同的方案,这样下来整道题就组合数方案就很复杂。
后来发现用记忆递归结合深搜可以试一下


2.代码:

#include<iostream>
#include<cstring>
using namespace std;

const int MOD=1000000007;
int n,m,k;
int data[50][50];

long long ans;
long long cache[50][50][14][13];//cache数组中记录的是状态   x、y坐标 拥有宝物数量 拥有宝物的最大值 
     //如cache[3][4][5][6]=7 即当在map[3][4]且身上有5件宝物 宝物的最大值是6 是到达终点有7中路径
     //可以将入口定义为坐标(0,0) 
void dfs(int x,int y,int max,int cnt){}
long long dfs2(int x,int y,int max,int cnt){  //当前位置   拥有宝物的数量 拥有的宝物的最大值
	//查缓存 
	if(cache[x][y][max+1][cnt!=-1]) //判断这个状态是否已经走过,如果走过就直接用记录的数值计算
	//因为宝物有可能为0所以定义max时用最小值-1 这就导致无法作为下标使用  实际上如果测试数据中宝物价值没有0
	   //将所有的+1 去掉也是可以的   这里的话如果去掉肯定是有些数据不对的
	return cache[x][y][max+1][cnt];
	long long ans=0;
	if(x==n||y==m||cnt>k)   //向右走到n或者向下走到m或者宝物数量达到最大,满足其中一个即可 
	return 0;
	int cur=data[x][y]; //当前坐标位置 
	if(x==n-1&&y==m-1) //已经面临最后一个格子
	{
		if(cnt==k||(cnt==k-1&&cur>max)){
			ans++;
			if(ans>MOD)
			ans%=MOD;
		}
		return ans;
	 } 
	 
	 if(cur>max){ //可以取这个物品 
	 ans+=dfs2(x,y+1,max,cnt); //向左走 
	 ans+=dfs2(x+1,y,max,cnt);  //向右走 
	 } 
	 //对于价值较小,或者价值大,可以不去取这个物品的情况
	 ans+=dfs2(x,y+1,max,cnt);
	 ans+=dfs2(x+1,y,max,cnt); 
	 cache[x][y][max+1][cnt]=ans%MOD;
	 return ans%MOD;
	 }
	 int main(){
	 	scanf("%d %d %d",&n,&m,&k);
	 	for(int i=0;i<n;i++){
	 		for(int j=0;j<n;j++){
	 			scanf("%d",&data[i][j]);
			 }
		 }
		 dfs(0,0,-1,0);  //第一个点的价值可能为0
		 memset(cache,-1,sizeof(cache));
		 printf("%lli\n",dfs2(0,0,-1,0));
		 return 0; 
	 }

发布了106 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/gl620321/article/details/105011097
今日推荐