问题描述
  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. idea编辑器HttpServlet httpServlet = ServletActionContext.getServletContext().getRealPath();方法无法使用

    HttpServlet httpServlet = ServletActionContext.getServletContext().getRealPath(); 前几天在使用idea的时候发现这个方 ...

  2. Java多线程同步问题的探究

    一.线程的先来后到——问题的提出:为什么要有多线程同步?Java多线程同步的机制是什么? http://www.blogjava.net/zhangwei217245/archive/2010/03/ ...

  3. iOS - OC NSData 数据

    前言 @interface NSData : NSObject <NSCopying, NSMutableCopying, NSSecureCoding> @interface NSMut ...

  4. [转载] TCP协议缺陷不完全记录

    原文: http://www.blogjava.net/yongboy/archive/2015/05/07/424917.html tcp是一个非常复杂并且古老的协议, 之前教科书上将的很多东西应用 ...

  5. EF执行存储过程

    //执行strSql/procSql //返回受影响的行数 int i = dbsql.Database.ExecuteSqlCommand("exec getActionUrlId @na ...

  6. vitamio框架

    import io.vov.vitamio.LibsChecker; import io.vov.vitamio.MediaPlayer; import io.vov.vitamio.MediaPla ...

  7. Android:控件WebView显示网页

    WebView可以使得网页轻松的内嵌到app里,还可以直接跟js相互调用. webview有两个方法:setWebChromeClient 和 setWebClient setWebClient:主要 ...

  8. Mysql中的排序规则utf8_unicode_ci、utf8_general_ci的区别总结

    Mysql中utf8_general_ci与utf8_unicode_ci有什么区别呢?在编程语言中,通常用unicode对中文字符做处理,防止出现乱码,那么在MySQL里,为什么大家都使用utf8_ ...

  9. 转:内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区[C++][内存管理][转载]

    内存区划分.内存分配.常量存储区.堆.栈.自由存储区.全局区[C++][内存管理][转载] 一. 在c中分为这几个存储区1.栈 - 由编译器自动分配释放2.堆 - 一般由程序员分配释放,若程序员不释放 ...

  10. commonJS — 对象操作(for Object)

    for Object github: https://github.com/laixiangran/commonJS/blob/master/src/forObject.js 代码 /** * Cre ...