问题描述
  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
 
暴力dfs会超时,可以dp或者记忆化搜索....理解可以...自己写可能就....gg了...
这样的话,感觉还是记忆化搜索更萌一些,因为不用考虑那么多边界...
思路见代码.
dp:
/*
蓝桥杯历届试题地宫寻宝 dp
状态:dp[i][j][num][val] 表示从起点(1, 1)走到(i, j), 已经取了num个宝物,最大价值是val 的方案数。
初态:dp[1][1][0][0] = 1; dp[1][1][1][mp[1][1]] = 1;
转移方程:由上方或者左方的格子转移而来,详见代码;
*/ #include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std; #define mod 1000000007
int dp[55][55][15][15];
int mp[55][55]; int main() {
int n, m, k;
while(~scanf("%d%d%d", &n, &m, &k)) {
for (int i=1; i<=n; ++i) {
for (int j=1; j<=m; ++j) {
scanf("%d", &mp[i][j]);
}
} memset(dp, 0, sizeof(dp));
dp[1][1][0][0] = 1;
dp[1][1][1][mp[1][1]] = 1; for (int i=1; i<=n; ++i) {
for (int j=1; j<=m; ++j) {
dp[i][j][0][0] += (dp[i-1][j][0][0] + dp[i][j-1][0][0]);
dp[i][j][0][0] %= mod;
for (int num=1; num<=k; ++num) {
for (int val=0; val<=12; ++val) {
dp[i][j][num][val] += (dp[i-1][j][num][val] + dp[i][j-1][num][val]);
dp[i][j][num][val] %= mod;
}
if (num == 1) {
dp[i][j][1][mp[i][j]] += dp[i-1][j][0][0];
dp[i][j][1][mp[i][j]] %= mod;
dp[i][j][1][mp[i][j]] += dp[i][j-1][0][0];
dp[i][j][1][mp[i][j]] %= mod;
}
else {
for (int t=0; t<mp[i][j]; ++t) {
dp[i][j][num][mp[i][j]] += dp[i-1][j][num-1][t];
dp[i][j][num][mp[i][j]] %= mod;
dp[i][j][num][mp[i][j]] += dp[i][j-1][num-1][t];
dp[i][j][num][mp[i][j]] %= mod;
}
}
}
}
} int ans = 0;
for (int i=0; i<=12; ++i) {
ans += dp[n][m][k][i];
ans %= mod;
}
printf("%d\n", ans);
}
return 0;
}

记忆化搜索:

/*
蓝桥杯历届试题 地宫取宝 dp[i][j][num][k] 表示到位置(i, j)时, 取了第num个宝藏,最大宝藏值是k时,
能到终点的路线方案数。 dfs超时。
记忆化搜索...
*/ #include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define mod 1000000007 int dp[55][55][15][15];
int n, m, k;
int mp[55][55]; int dfs(int nowx, int nowy, int cnt, int nowMax) {
if (dp[nowx][nowy][cnt][nowMax+1] != -1) {
return dp[nowx][nowy][cnt][nowMax+1];
}
int ans = 0;
if (nowx == n-1 && nowy == m-1) {
if (mp[nowx][nowy] > nowMax) {
if (cnt == k || cnt == k-1)
ans++;
ans %= mod;
}
else if (cnt == k) ans++;
ans %= mod;
return dp[nowx][nowy][cnt][nowMax+1] = ans;
} if (nowx+1 < n) {
if (mp[nowx][nowy] > nowMax) {
ans += dfs(nowx+1, nowy, cnt+1, mp[nowx][nowy]);
ans %= mod;
}
ans += dfs(nowx+1, nowy, cnt, nowMax);
ans %= mod;
}
if (nowy+1 < m) {
if (mp[nowx][nowy] > nowMax) {
ans += dfs(nowx, nowy+1, cnt+1, mp[nowx][nowy]);
ans %= mod;
}
ans += dfs(nowx, nowy+1, cnt, nowMax);
ans %= mod;
}
return dp[nowx][nowy][cnt][nowMax+1] = ans;
} int main() {
while(~scanf("%d%d%d", &n, &m, &k)) {
memset(dp, -1, sizeof(dp));
for (int i=0; i<n; ++i) {
for (int j=0; j<m; ++j) {
scanf("%d", &mp[i][j]);
}
}
int ans = dfs(0, 0, 0, -1);
printf("%d\n", ans);
}
return 0;
}

  

蓝桥杯历届试题 地宫取宝 dp or 记忆化搜索的更多相关文章

  1. Java实现 蓝桥杯 历届试题 地宫取宝

    问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. 走 ...

  2. 算法笔记_174:历届试题 地宫取宝(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明 ...

  3. 【bzoj1415】【聪聪和可可】期望dp(记忆化搜索)+最短路

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=57148470 Descrition 首先很明显是 ...

  4. 二进制数(dp,记忆化搜索)

    二进制数(dp,记忆化搜索) 给定k个<=1e6的正整数x(k不大于10),问最小的,能被x整除且只由01组成的数. 首先,dp很好写.用\(f[i][j]\)表示i位01串,模ki的值是j的数 ...

  5. poj1179 区间dp(记忆化搜索写法)有巨坑!

    http://poj.org/problem?id=1179 Description Polygon is a game for one player that starts on a polygon ...

  6. 2017广东工业大学程序设计竞赛决赛 题解&源码(A,数学解方程,B,贪心博弈,C,递归,D,水,E,贪心,面试题,F,贪心,枚举,LCA,G,dp,记忆化搜索,H,思维题)

    心得: 这比赛真的是不要不要的,pending了一下午,也不知道对错,直接做过去就是了,也没有管太多! Problem A: 两只老虎 Description 来,我们先来放松下,听听儿歌,一起“唱” ...

  7. 【BZOJ3769】spoj 8549 BST again DP(记忆化搜索?)

    [BZOJ3769]spoj 8549 BST again Description 求有多少棵大小为n的深度为h的二叉树.(树根深度为0:左右子树有别:答案对1000000007取模) Input 第 ...

  8. HDU 3652 B-number(数位dp&amp;记忆化搜索)

    题目链接:[kuangbin带你飞]专题十五 数位DP G - B-number 题意 求1-n的范围里含有13且能被13整除的数字的个数. 思路 首先,了解这样一个式子:a%m == ((b%m)* ...

  9. 【CF607B】Zuma——区间dp(记忆化搜索/递推)

    以下是从中文翻译成人话的题面: 给定一个长度小于等于500的序列,每个数字代表一个颜色,每次可以消掉一个回文串,问最多消几次可以消完? (7.16) 这个题从洛谷pend回来以后显示有103个测试点( ...

随机推荐

  1. iOS - Swift SingleClass 单例类

    前言 单例对象能够被整个程序所操作.对于一个单例类,无论初始化单例对象多少次,也只能有一个单例对象存在,并且该对象是全局的,能够被整个系统访问到. 单例类的创建 1.1 单例类的创建 1 单例类的创建 ...

  2. web设计经验<六>令网站看起来不专业的10个设计误区

    不管你是不是一个羽翼未丰企业的领导,专业的网站能为你带来的东西比你想象的多很多.退一万步来说,“考虑到我们是一个小厂”,粗糙的网站也许能被用户理解,但是不一定能接受.每天大家所浏览的大量的网站,已经从 ...

  3. Python学习(13)函数

    目录 Python 函数 函数调用 匿名函数 return语句 变量作用域 Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复 ...

  4. maven入门

    1.1.项目构建 Maven(翻译为"专家","内行")是跨平台的项目管理工具.主要服务于基于Java平台的项目构建,依赖管理和项目信息管理. 项目构建过程包括 ...

  5. Object Pascal 过程与函数

    过程与函数 过程与函数是实现一定功能的语句块,是程序中的特定功能单元.可以在程序的其他地方被调用,也可以进行递归调用.过程与函数的区别在于过程没有返回值,而函数有返回值. 1.过程与函数的定义 过程与 ...

  6. WebKit渲染基础(转载 学习中。。。)

    概述 WebKit是一个渲染引擎,而不是一个浏览器,它专注于网页内容展示,其中渲染是其中核心的部分之一.本章着重于对渲染部分的基础进行一定程度的了解和认识,主要理解基于DOM树来介绍Render树和R ...

  7. spring中的Log4jConfigListener作用和webapp.root的设置

    转:http://blog.sina.com.cn/s/blog_7bbf356c01016wld.html 使用spring中的Log4jConfigListener有如如下好处:     1. 动 ...

  8. Eclipse启动tomcat时报错:Multiple Contexts have a path of "/xxx"

    今天使用Eclipse启动tomcat部署项目时,遇到一个奇怪的错误: Could not publish server configuration for Tomcat v6.0 Server at ...

  9. php学习记录 易混淆

    1.echo和print的区别 PHP中echo和print的功能基本相同(输出),但是两者之间还是有细微差别的.echo输出后没有返回值,但print有返回值,当其执行失败时返回flase.因此可以 ...

  10. DOS命令行中的双引号

    在DOS命令窗口下,运行C:\Program Files\WinRAR\WinRAR.exe,提示如下错误: 因为C:\Program Files\WinRAR\WinRAR.exe中含有空格,它被分 ...