蓝桥杯 历届试题 地宫取宝 【记忆化搜索】

历届试题 地宫取宝

时间限制:1.0s   内存限制:256.0MB

问题描述

  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

来自网上:

#include <iostream>
#include <cstring>
const int N = 1e9+7;
const int M = 55;
using namespace std;

int dp[M][M][15][15], n, m, k;  //四维数组就是将每一个状态值都先初始化,然后在后面如果改变了,如果下一次有用到这个状态,那么直接用就好了。
int map[M][M];

int dfs(int x, int y, int num, int max){  //max表示当前最大值
	if(dp[x][y][num][max+1] != -1){  //记忆化
		return dp[x][y][num][max+1];
	}
	int t = 0;//初始化
	if(x == n-1 && y == m-1){  //到了右下角
		if(map[x][y] > max){
			if(num == k|| num == k-1) ++t; //可以拿也可以不拿
		}
		else if(num == k) ++ t;  //表示不拿
		return dp[x][y][num][max+1] = t;  //因为初始参数是-1,所以要加1
	}
	if(x+1 < n){  //向下
		if(map[x][y] > max){
			t += dfs(x+1, y, num+1, map[x][y]);
			t %= N;
		}
		t += dfs(x+1, y, num, max);
		t %= N;
	}
	if(y+1 < m){ //向右
		if(map[x][y] > max){
			t += dfs(x, y+1, num+1, map[x][y]);
			t %= N;
		}
		t += dfs(x, y+1, num, max);
		t %= N;
	}
	dp[x][y][num][max+1] = t;  //记忆化
	return dp[x][y][num][max+1];
}

int main(){
	cin >> n >> m >> k;
	for(int i = 0; i < n; ++ i)
	for(int j = 0; j < m; ++ j)
	cin >>map[i][j];
	memset(dp, -1, sizeof(dp));
	dp[0][0][0][0] = dfs(0, 0, 0, -1);
	cout << dp[0][0][0][0] <<endl;
	return 0;
}

自己写的一个代码只过了3组。。。其他超时,,而且测试数据2都没过。。。

代码:

#include <iostream>
#include <cstring>
const int N = 1e9+7;
const int M = 55;
using namespace std;

int dp[M][M][15][15], n, m, k;
int map[M][M];

int dfs(int x, int y, int num, int max){
	if(dp[x][y][num][max+1] != -1){
		return dp[x][y][num][max+1];
	}
	int t = 0;
	if(x == n-1 && y == m-1){
		if(map[x][y] > max){
			if(num == k|| num == k-1) ++t;
		}
		else if(num == k) ++ t;
		return dp[x][y][num][max+1] = t;
	}
	if(x+1 < n){
		if(map[x][y] > max){
			t += dfs(x+1, y, num+1, map[x][y]);
			t %= N;
		}
		t += dfs(x+1, y, num, max);
		t %= N;
	}
	if(y+1 < m){
		if(map[x][y] > max){
			t += dfs(x, y+1, num+1, map[x][y]);
			t %= N;
		}
		t += dfs(x, y+1, num, max);
		t %= N;
	}
	dp[x][y][num][max+1] = t;
	return dp[x][y][num][max+1];
}

int main(){
	cin >> n >> m >> k;
	for(int i = 0; i < n; ++ i)
	for(int j = 0; j < m; ++ j)
	cin >>map[i][j];
	memset(dp, -1, sizeof(dp));
	dp[0][0][0][0] = dfs(0, 0, 0, -1);
	cout << dp[0][0][0][0] <<endl;
	return 0;
}

历届试题 地宫取宝

时间限制:1.0s   内存限制:256.0MB

问题描述

  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

时间: 2024-10-12 19:32:15

蓝桥杯 历届试题 地宫取宝 【记忆化搜索】的相关文章

蓝桥杯历届试题 地宫取宝 dp or 记忆化搜索

问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. 走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿). 当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明. 请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝. 输入格式 输入一行3个整数,用空格分开:n

蓝桥杯竞赛题《地宫取宝》DP做法

问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. 走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿). 当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明. 请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝. 输入格式 输入一行3个整数,用空格分开:n

蓝桥杯 历届试题 题目总结

后天就是蓝桥杯省赛了,今天总结一下这段时间做的蓝桥杯历届试题,还是一个一个题目的来吧!!!!!! 1,历届试题 矩阵翻硬币 这个题目说真的,我不会,在网上看了某神牛的题解答案为 ans=sqrt(n)*sqrt(m),具体怎么证明的我也不知道 2,历届试题 兰顿蚂蚁 这个题目怎么说呢,应该是送分题,直接模拟就可以了,这里就不说了. 3, 历届试题 分糖果 这个题目好像之前在哪里做过,也是一道模拟题,弄两个数组搞一下就可以了 下面是代码 #include<bits/stdc++.h> using

蓝桥杯-历届试题之大臣的旅费

历届试题 大臣的旅费 时间限制:1.0s   内存限制:256.0MB 问题描述 很久以前,T王国空前繁荣.为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市. 为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达.同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的. J是T国重要大臣,他巡查于各大城市之间,体察民情.所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情.他有一个钱袋,用于

【BZOJ-3895】取石子 记忆化搜索 + 博弈

3895: 取石子 Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 263  Solved: 127[Submit][Status][Discuss] Description Alice和Bob两个好朋含友又开始玩取石子了.游戏开始时,有N堆石子 排成一排,然后他们轮流操作(Alice先手),每次操作时从下面的规则中任选一个: ·从某堆石子中取走一个 ·合并任意两堆石子 不能操作的人输.Alice想知道,她是否能有必胜策略. Input 第一行输入T

蓝桥杯 历届试题 连号区间数

历届试题 连号区间数 时间限制:1.0s   内存限制:256.0MB 问题描述 小明这些天一直在思考这样一个奇怪而有趣的问题: 在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是: 如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的"连续"数列,则称这个区间连号区间. 当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助. 输入格式 第一行是一个正整数N (1 &

蓝桥杯 历届试题 带分数 DFS最容易理解版,内有解析

历届试题 带分数 时间限制:1.0s   内存限制:256.0MB 问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. 注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0). 类似这样的带分数,100 有 11 种表示法. 输入格式 从标准输入读入一个正整数N (N<1000*1000) 输出格式 程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数. 注意:不要求输出每个表示,

蓝桥杯 历届试题 大臣的旅费 DFS两次

历届试题 大臣的旅费 时间限制:1.0s   内存限制:256.0MB 问题描述 很久以前,T王国空前繁荣.为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市. 为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达.同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的. J是T国重要大臣,他巡查于各大城市之间,体察民情.所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情.他有一个钱袋,用于

蓝桥杯 历届试题 PREV-34 矩阵翻硬币

历届试题 矩阵翻硬币 时间限制:1.0s   内存限制:256.0MB 问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转. 其中i和j为任意使操作可行的正整数,行号和列号都是从1开始. 当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹--所有硬币均为正面朝上. 小明想知道最开始有多少枚硬币是反面朝上的.于是,他向他的好朋友小M寻求帮助.