地宫取宝 (第五届蓝桥杯省赛C++A/B组)
题意描述
X 国王有一个地宫宝库,是 n×m 个格子的矩阵,每个格子放一件宝贝,每个宝贝贴着价值标签。 地宫的入口在左上角,出口在右下角。 小明被带到地宫的入口,国王要求他只能向右或向下行走。 走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。 当小明走到出口时,如果他手中的宝贝恰好是 k 件,则这些宝贝就可以送给小明。 请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 k 件宝贝。
输入格式 第一行 3 个整数,n,m,k,含义见题目描述。 接下来 n 行,每行有 m 个整数 Ci 用来描述宝库矩阵每个格子的宝贝价值。
输出格式 输出一个整数,表示正好取 k 个宝贝的行动方案数。 该数字可能很大,输出它对 1000000007 取模的结果。
数据范围 1≤n,m≤50, 1≤k≤12, 0≤Ci≤12
输入样例1: 2 2 2 1 2 2 1 输出样例1: 2 输入样例2: 2 3 2 1 2 3 2 1 5 输出样例2: 14
思路
这是一道动态规划的题目。我们可以用yxc的集合方法来分析动态规划。可以用dp[i][j][k][l]来表示,从起点到(i,j)点时,取得物品的数量为k,且最后一件取得的物品价值为l的方案数量,通过分析,我们可以发现,走到最后一步的方案数等于最后一步是从上走下来的方案数和最后一步是从左走过来的方案数相加,而最后一步又有取和不取两种情况,如果不取最后一件的话,那么状态方程很容易表示出来;如果取最后一件,则会比较复杂。根据题意,我们每次所取的最后一件一定是最大的,所以我们一定会有一个限定条件,即W==g[i][j],如果满足这个条件,那么就再进行一次循环,将方案数相加即可。关于细节问题,由于我们要选的是方案数,所以与物品价值大小无关。如果选第一件物品,则有初值dp[1][1][1][g[1][1]]=1。如果不选,则有dp[1][1][0][0]=1。
AC代码
#include<iostream>
using namespace std;
const int N=55;
const int MOD=1e9+7;
int dp[N][N][13][14];
int g[N][N];
int n,m,k;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>g[i][j];
g[i][j]++;
}
}
dp[1][1][1][g[1][1]]=1;
dp[1][1][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int u=0;u<=k;u++){
for(int v=0;v<=13;v++){
dp[i][j][u][v]=(dp[i][j][u][v]+dp[i-1][j][u][v])%MOD;
dp[i][j][u][v]=(dp[i][j][u][v]+dp[i][j-1][u][v])%MOD;
if(u>0&&v==g[i][j]){
for(int c=0;c<v;c++){
dp[i][j][u][v]=(dp[i][j][u][v]+dp[i-1][j][u-1][c])%MOD;
dp[i][j][u][v]=(dp[i][j][u][v]+dp[i][j-1][u-1][c])%MOD;
}
}
}
}
}
}
int res=0;
for(int i=0;i<=13;i++) res=(res+dp[n][m][k][i])%MOD;
cout<<res<<endl;
return 0;
}
- 【C++概念】---vector用法
- 浅谈Orabbix监控指标(r6笔记第27天)
- Orabbix定制监控Oracle的简单配置(r6笔记第26天)
- 【java基础】 线程实例
- 记一次数据库的分析和优化建议(r6笔记第24天)
- linux (ubantu)安装最新版python3.6,以及直接安装anaconda
- 【java基础】匿名类
- 朴素贝叶斯法 2016年11月11日
- 11g中关于控制文件自动备份的改进(r6笔记第22天)
- Java基础(02)-15总结对象数组,集合Collection,集合List
- alert日志中的两种ORA错误分析(r6笔记第21天)
- 通过定制orabbix监控分析潜在的Oracle问题 (r6笔记第32天)
- 【C语言练手】C语言画太极图
- 关于奇怪的并行进程分析(一) (r6笔记第41天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 思科模拟器GNS3将路由器变成交换机的方法
- docker安装nginx并配置https
- Docker Swarm集群部署lnmp+redis
- Maven快速入门
- TomCat安装及快速部署
- SpringCloud+MyBatis分页处理(前后端分离)
- 手把手教你搭建SpringCloud项目
- SpringCloud的@Value注解及GitLab配置使用
- 使用 cdk8s 与 Argo CD 进行 GitOps 实践
- 设计模式 | 模版方法
- Python 函数3000字使用总结
- 3D摇杆控制器一种简单实现!Cocos Creator 3D!
- 数据结构 | TencentOS-tiny中队列、环形队列、优先级队列的实现及使用
- RTOS内功修炼记(六)—— 任务间通信为什么不用全局变量?
- 程序员必备基础:加签验签