地宫夺宝(三种方法)(第五届蓝桥杯省赛C++A/B/C组,第五届蓝桥杯省赛JAVAB/C组)

news2024/11/15 19:37:42

 PS:方法一和方法看起来复杂,但其实较容易理解,大家不要跳过哦。至于方法三的动态规划则可能有点抽象,理解起来有点难度。


目录

题目描述:

三种方法:

方法一:暴力枚举(该方法只能获得30分)

思路:

详细代码:

方法二:暴力枚举+记忆化搜索(该方法可获得满分)

思路:

详细代码:

方法三:动态规划(该方法可获得满分)

思路:

 详细代码:


题目描述:

三种方法:

对于这个题目

博主在这里介绍三种不同的方法

方法一:暴力枚举(该方法只能获得30分)

该方法是对于实在没有时间

或者想不到要怎么进行下一步而提供的

骗分的方法(有时候的几十分就一个奖项等级的差距)

思路:

如果大家实在是没有思路的话

就建议大家直接采用暴力

主要的思路就是暴力枚举

每一种从左上角到右下角的方法

然后对合法的方法相加

详细代码:

#include<iostream>
using namespace std;
const int N=56;
const int Mo=1000000007;

int a[N][N];

int n,m,k;

//h表示行,l表示列,Have表示目前有多少个宝物,MaxVal表示所持的物品中物品最大的价值为多少
int dg(int h,int l,int Have,int MaxVal){
    //对于合法的方案数的判断,注意不要漏掉到达出口也可以取出口的宝物的情况
    if(h==n&&l==m&&(Have==k||(MaxVal<a[h][l]&&Have+1==k))){
        return 1;
    }
    
    //如果移动超过界限,或者持有宝物已经超过了k,可以直接返回方案数为0,即不合法
    if(h>n||l>m||Have>k) {
        return 0; 
    }
    
    //不选(h,j)上的宝物的情况
    int NotChoose=(dg(h+1,l,Have,MaxVal)+dg(h,l+1,Have,MaxVal))%Mo;
    
    int Choose=0;
    //选择(h,j)上的宝物的情况
    if(MaxVal<a[h][l]){//判断能否取该位置的宝物,即该位置的宝物价值大于所持有的所有宝物
        Choose=(dg(h+1,l,Have+1,a[h][l])+dg(h,l+1,Have+1,a[h][l]))%Mo;
    }
    
    return (NotChoose+Choose)%Mo;//返回两种选择的方案数的和
}


int main(){
    cin>>n>>m>>k;
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            {
            	scanf("%d",&a[i][j]);
            	a[i][j]++;//把所有宝贝的价格都加1,方便处理
			}
    
    int ans=dg(1,1,0,0)%Mo;
    
    cout<<ans;
    return 0;
}

方法二:暴力枚举+记忆化搜索(该方法可获得满分)

方法二则就是在方法一的基础上

加上了记忆化搜索

提高了算法的效率

思路:

对于在方法一中的暴力枚举

我们可以发现其实很多步骤

会进行重复计算

所以我们把方案数记录下来

可以节省很多的时间

注意这里的recorded数组记录下来的

是从recorded[h][l][Have][MaxVal]到

出口合法的方案数

详细代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=56;
const int M=16;
const int Mo=1000000007;

int a[N][N];
int recorded[N][N][M][M];

int n,m,k;

//h表示行,l表示列,Have表示目前有多少个宝物,MaxVal表示所持的物品中物品最大的价值为多少
int dg(int h,int l,int Have,int MaxVal){
    //对于合法的方案数的判断,注意不要漏掉到达出口也可以取出口的宝物的情况
    if(h==n&&l==m&&(Have==k||(MaxVal<a[h][l]&&Have+1==k))){
        recorded[h][l][Have][MaxVal]=1;
        return 1;
    }
    
    //如果移动超过界限,或者持有宝物已经超过了k,可以直接返回方案数为0,即不合法
    if(h>n||l>m||Have>k) {
        recorded[h][l][Have][MaxVal]=0;
        return 0; 
    }
    
    //如果曾经被记忆过则直接使用
    if(-1!=recorded[h][l][Have][MaxVal]) return recorded[h][l][Have][MaxVal];
    
    //不选(h,j)上的宝物的情况
    int NotChoose=(dg(h+1,l,Have,MaxVal)+dg(h,l+1,Have,MaxVal))%Mo;
    
    int Choose=0;
    //选择(h,j)上的宝物的情况
    if(MaxVal<a[h][l]){//判断能否取该位置的宝物,即该位置的宝物价值大于所持有的所有宝物
        Choose=(dg(h+1,l,Have+1,a[h][l])+dg(h,l+1,Have+1,a[h][l]))%Mo;
    }
    
    //对于方案数进行记忆
    recorded[h][l][Have][MaxVal]=(NotChoose+Choose)%Mo;
    
    //返回两种选择的方案数的和
    return (NotChoose+Choose)%Mo;
}


int main(){
    cin>>n>>m>>k;
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            {
            	scanf("%d",&a[i][j]);
            	a[i][j]++;
			}
    
    //将recorded都赋值为-1,方便后期进行判断
    memset(recorded,-1,sizeof(recorded));
    
    int ans=dg(1,1,0,0)%Mo;
    
    cout<<ans;
    return 0;
}

方法三:动态规划(该方法可获得满分)

思路:

方法三则是使用动态规划

进行解题

利用四维数组递推每一种合法的方法

 详细代码:

#include<iostream>
using namespace std;

const int N=56;
const int M=16;
const int Mo=1000000007;

int f[N][N][M][M];
//f[i][j][u][v]:i和j表示位置,u表示取了u个物品,v表示取的物品中的最高价值
int a[N][N];

int main(){
    int n,m,k;
    cin>>n>>m>>k;
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            a[i][j]++;//为了方便处理边界,将每件物品的价值+1
        }
    
    //初始化方法数:
    f[1][1][1][a[1][1]]=1;//让第(1,1)位置,取该位置上的宝贝的方案数为1
    f[1][1][0][0]=1;//让第(1,1)位置,不取该位置上的宝贝的方案数为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++){
                    //i和j表示位置,u表示取了u个物品,v表示取的物品中的最高价值
                    int &now=f[i][j][u][v];//别名,相当于用now代表了f[i][j][u][v]
                    
                    //不取a[i][j]的方案数
                    now=(now+f[i-1][j][u][v])%Mo;//加上 从下边到达(i,j) 并不取该位置的宝贝的方案数
                    now=(now+f[i][j-1][u][v])%Mo;//加上 从左边到达(i,j) 并不取该位置的宝贝的方案数
                    
                    //取a[i][j],那么该位置的价值一定为a[i][j],因为a[i][j]为取的物品中的最高价值
                    if(v==a[i][j]){//这里没有判断u等于0的情况是因为u=0时v=0,不会进入判断
                        for(int tv=0;tv<v;tv++){
                            now=(now+f[i-1][j][u-1][tv])%Mo;//加上 从下边到达(i,j) 并取该位置的宝贝的方案数
                            now=(now+f[i][j-1][u-1][tv])%Mo;//加上 从左边到达(i,j) 并取该位置的宝贝的方案数
                        }
                    }
                }
    
    int ans=0;
    for(int i=1;i<=13;i++){//将能够取到k件宝贝的所有方案数相加即是答案(因为最大价值的取值只能从1到13)
        ans=(ans+f[n][m][k][i])%Mo;
    }
    cout<<ans;
    return 0;
}

PS:比赛场上遇见题目,我们的目标并不是去找到每一个题目的最优解,而是找到对于我们来说能够快速做出题目,并能够获取高分的题目。希望大家都能获得一个满意的成绩。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/134561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

函数传参问题,桶排序去重,分治递归,摩尔投票求数组众数,数组中心下标求法

TIPS 1. 我们都知道&#xff0c;地址&#xff0c;指针这两者是完全等价的概念&#xff0c;但是有微小的差别。地址的话是不能够修改的&#xff08;比如说数组名就是违法的&#xff09;&#xff0c;而指针的话可以与--。 2. 以后一旦在代码里面看到字符char类型的&#xff0c;…

安全回顾总结

xss反射型漏洞复现 观察源码&#xff0c;可以看出源码中通过get传参到变量xss&#xff0c;并将一些特殊符号过滤了&#xff0c;则后续需要考虑该规则的绕过 echo “<img src”{$xss}">"; img标签 <img src“aaa” οnerrοr“alert(1)” 如果img图片不存在…

自然语言处理-01神经网络

数学和PY 向量是同时拥有大小和方向的量。向量可以表示为排成一排的数字集合&#xff0c;在 Python 实现中可以处理为一维数组。 向量和矩阵可以分别用一维数组和二维数组表示。另外&#xff0c;在矩阵中&#xff0c;将水平方向上的排列称为行&#xff08;row&#xff09;&…

2.SpringBoot-Condition

一、 参考 04-SpringBoot自动配置-切换内置web服务器_哔哩哔哩_bilibili 二、 Condition 顾名思义&#xff1a;条件。有点类似于if语句&#xff0c;只不过是通过注解的形式来实现。 以一个实际需求来学习该原理&#xff1a;有一个实体类User&#xff0c;想要创建该实例化对象…

Retrift

文章目录一、Retrift简介二、Retrift使用介绍三、注解1、GET2、POST3、PUT4、DELETE一、Retrift简介 retrift官网 1、是一个基于okhttp的网络请求框架 2、通过注解配置网络请求参数 3、图片链接和图片上传 4、支持同步和异步网络请求 5、支持多种数据的解析,提供对Rxjava的支…

光环:软件工程环境堆栈建设思路——徐磊

摘要&#xff1a;文章内容主要来源于光环国际2022年第三届中国科创者大会徐磊老师的分享&#xff0c;原分享名称为"企业开发者平台建设思路&#xff0c;云原生技术如何赋能开发者"。简述当前软件工程中Devops平台还缺少一个软件调试环境环节&#xff0c;这个环境其实…

stacking方法,boosting算法,与bagging的区别,adboost算法权重固定,regionboost权重动态学习

stacking方法&#xff0c;boosting算法&#xff0c;与bagging的区别&#xff0c;adboost算法权重固定&#xff0c;regionboost权重动态学习 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#…

VBA之正则表达式(38)-- 提取规格数据(1/2)

实例需求&#xff1a;A列为某产品名称&#xff0c;现需要提取其中的规格数据&#xff0c;具体规则如下&#xff1a; 规格数据以如下关键字开头&#xff1a;RO、RE、SQ、SD、QD、OB、HX、ET、QR、D2规则数据可能有多段&#xff08;截图中红色部分&#xff09;提取规格数据之后&…

数据模拟:利用Java模拟数据(姓名,邮箱,地址,电话等信息,时间,工资,1-10随机数)并存入mysql

学大数据分析的同学们在做数据分析时一般很难找到适合数据集&#xff0c;本文就来分享一下如何利用Java模拟数据&#xff0c;并将产生数据保存至mysql数据库中。 主要技术就是Java产生数据&#xff0c;利用mybatis存入mysql数据库 数据模拟项目1.数据库建表2.构建maven项目3.项…

初级指针【一】

指针是什么&#xff1f;2个要点&#xff1a;指针是内存中一个最小单元编号&#xff0c;也就是地址。平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用来存放地址的变量。总结&#xff1a;指针就是地址&#xff0c;我们口语中说的指针指的是指针变量。指针的大…

ZooKeeper分布式协调服务(节点分类、事件监听、java集成)

文章目录前言安装启动相关概念操作节点事件监听java客户端前言 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xf…

序列化二叉树 - 剑指Offer困难

序列化二叉树 题目链接 请实现两个函数&#xff0c;分别用来序列化和反序列化二叉树。 你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑&#xff0c;你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为…

Alibaba Clould Tookit插件-IDEA实现一键部署

Alibaba Clould Tookit插件-IDEA实现一键部署 文章目录 前言说明使用 安装插件配置服务添加服务配置打包上传等内容 配置自动化配置命令配置文件上传前执行的命令 远程发布查看是否成功注意脚本 前言 本来一直使用jenkins后来坏掉了&#xff0c;别问&#xff0c;问就是老板…

(三分钟了解)处理外点(粗差)的方法--ransac和M估计

​ 编辑 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 外点也即是我们所说的粗差&#xff0c;是因为在实际工程当中由于人为因素或者测量设备等因素造成的测量值与实际情况相比误差较大。然后从高斯分布的角度来说就是大于3σ以外的数据。本篇博客将…

STM32——OLED调试工具与显示屏

文章目录一、调试工具二、OLED简介三、硬件电路接线图四、OLED驱动函数五、源码OLED.cOLED.hOLED_Font.h一、调试工具 调试方式 串口调试&#xff1a;通过串口通信&#xff0c;将调试信息发送到电脑端&#xff0c;电脑使用串口助手显示调试信息 显示屏调试&#xff1a;直接将…

ip综合实验

目录实验要求分析开始实施1&#xff0c;前期工作2&#xff0c;缺省路由配置3&#xff0c;hdlc封装4&#xff0c;ppp封装的pap认证5&#xff0c;ppp封装的chap认证6&#xff0c;构建MGRE环境nhrp协议7&#xff0c;RIP使内网互通水平分割关闭实验要求分析 1&#xff0c;如图为实…

2023前端二面高频vue面试题集锦

vuex是什么&#xff1f;怎么使用&#xff1f;哪种功能场景使用它&#xff1f; Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。vuex 就是一个仓库&#xff0c;仓库里放了很多对象。其中 state 就是数据源存放地&#xff0c;对应于一般 vue 对象里面的 data 里面存放的数据…

Js es6 Promise理解和使用

js中的promise是一个异步编程的解决方案&#xff0c;语法层面上他是一个构造函数&#xff0c;名字为Promise()。 它的作用就是将一个任务task封装为一个Promise类的实例对象&#xff0c;这个对象会将任务自动运行并得到任务结果&#xff0c;而且在得到结果的过程中并不会影响到…

告诉你应该选择 openSUSE 的五大理由

导读多数的的桌面 Linux 用户都会选择三种发行版本&#xff1a;Debian/Ubuntu、Fedora 或者 Arch Linux。但是今天&#xff0c;我将给出你需要使用 openSUSE 的五大理由。相比其他的 Linux 发行版&#xff0c;我总能在 openSUSE 上看到一些令人耳目一新的东西。我说不太好&…

多普勒效应(CSDN_0003_20220909)

目录 1. 机械波的多普勒效应 2. 电磁波的多普勒效应 文章编号&#xff08;CSDN_0003_20220909&#xff09; 由于原文公式较多&#xff0c;所以本文部分内容以截图的形式分享给大家&#xff0c;如果需要电子版原文&#xff0c;可留言或私信。 但凡提高雷达原理和雷达信号处理&a…