问题描述
  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. Jconsole 监控tomcat

    通过jconsole监控可以获取监控tomcat的相关的数据信息 如何通过代码来获取其中的线程和内存状况呢? 首先要配置好jconsole监控的相关配置,一搜基本就是那一个, 配置配不好的话接下来的工 ...

  2. oracle dba 职责, 及个人需要掌握内容

    ORACLE DBA 职责, 基本相当于日常工作. 0. 数据库设计 1. 模式对象的创建与管理(table, index 等等) 2. 事物管理, 例如并发等 3. SQL 调优 只是针对SQL的 ...

  3. 【Todo】pthread_key_t 和 pthread_once_t学习

    这两个函数应该都是和线程局部变量有关的.有时间学习一下. 可以参考如下文章: <Linux线程私有数据pthread_key_t> <posix多线程有感--线程高级编程(pthre ...

  4. Java 文件IO续

    文件IO续 File类    用来将文件和文件夹封装成对象 方便对文件和文件夹的属性信息进行操作    File对象可以作为参数传递给流的构造函数 Demo1 File的构造方法 public cla ...

  5. Date 与 switch的运用

    <html><head><title>日期</title><script>function toChinese(day){ switch(d ...

  6. MySQL 定时器EVENT学习

    原文:http://blog.csdn.net/lifuxiangcaohui/article/details/6583535 MySQL 定时器EVENT学习 MySQL从5.1开始支持event功 ...

  7. 自我总结(五)---(学习j2ee)

    自我完善的过程就是在不断的自我总结不断的改进. 我们这半个月来都是学习j2ee.这个知识是很重要的,一般我们出去工作都是会用到的.我们的星期六,星期天也是不上课的.所以说我相当于上了十天的j2ee了. ...

  8. LinuxShell脚本攻略--第一章 小试牛刀

    使用 shell 进行数学运算: #!/bin/bash no1=; no2=; let result=no1+no2 echo $result result=$[ $no1 + no2 ] resu ...

  9. 使用TCP/IP的套接字(Socket)进行通信

    http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html 使用TCP/IP的套接字(Socket)进行通信 套接字Socket的引入 ...

  10. Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio »迁移

    Migrations¶ 4 of 4 people found this helpful The Contoso University sample web application demonstra ...