蓝桥杯备赛day02 -- 算法训练题 拿金币Java

目录

题目:

问题描述

输入格式

输出格式

解题过程

第一步 定义dp数组

第二步 确定 dp 数组递推公式

 第三步 dp数组的初始化

第四步 dp数组的遍历顺序

第五步 举例说明

 报错:内存超限

用dp数组去存储位置上的金币

dp数组从二维降为一维

 收获:


 

题目:

问题描述

  有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。

输入格式

  第一行输入一个正整数n。
  以下n行描述该方格。金币数保证是不超过1000的正整数。

输出格式

  最多能拿金币数量。

样例输入

3
1 3 3
2 2 2
3 1 2

样例输出

11

数据规模和约定

n<=1000


解题过程

这是一道很明显的动态规划问题,那就老规矩动态规划五部曲。

第一步 定义dp数组

采用二维数组dp[ i ][ j ],定义为到第i行第j列时,拿到的最大金币数。

因此在定义数组长度时,需要是(n+1)*(n+1)

(因为数组索引从0开始)

又采用gold[ i ][ j ]数组,存储位置上的金币。

第二步 确定 dp 数组递推公式

我们只能往右走或者往下走,那么到达第i行第j列的位置,只能是从[ i ][ j-1 ]的位置(往右走)或者[ i-1 ][ j ] 的位置(往下走),

那么到[ i ][ j ]拿的金币应该为[ i ][ j-1 ][ i-1 ][ j ] 两者拿金币的最大值 加上[ i ][ j ]位置上的金币。

dp[i][j] = (Math.max(dp[i-1][j], dp[i][j-1]) + gold[i][j]);

 第三步 dp数组的初始化

  • 显然,在起点时,dp[1][1] = gold[1][1]
  • 在第一行时,我们只能往右走,这时dp[ i ][ j ] = dp[ i ][ j-1 ] + gold[ i ][ j ]。                         (注意往右是对 j 的变换,因此是 j-1 )
  • 在第一列时,我们只能往下走,这时dp[ i ][ j ] = dp[ i-1 ][ j ] + gold[ i ][ j ]。                         (注意往下是对i的变换,因此是 i-1 )

第四步 dp数组的遍历顺序

从左上角走到右下角,显然是i++,j++。 

第五步 举例说明

没啥可举例的哈。

最终代码如下,

import java.util.Scanner;
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[][] dp = new int [n+1][n+1];int[][] gold = new int [n+1][n+1];for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++ )gold[i][j] = scanner.nextInt();dp[1][1] = gold[1][1];for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) {if(i == 1 && j == 1) dp[i][j] = gold[1][1];else if(i == 1) dp[i][j] = dp[i][j-1] + gold[i][j];else if(j == 1) dp[i][j] = dp[i-1][j] + gold[i][j];else dp[i][j] = (Math.max(dp[i-1][j], dp[i][j-1]) + gold[i][j]);}}System.out.println(dp[n][n]);}
}

 报错:内存超限

乐,最终报错了,内存超限。十个评测记录,到第八个走不出来了。


随即就开始想办法优化。

要么将两个数组合并成一个数组,也就是用一开始用dp数组去存储位置上的金币,

要么将dp数组从二维降为一维。

用dp数组去存储位置上的金币

实际上操作跟之前没有什么不同,而且也是可行的。

因为数组是从左到右,从上到下遍历的dp[ i ][ j ] 修改后,就不需要起存储该位置上的金币的作用了,也就是时间错开了一下,从而起到数组有两个作用而不冲突。

代码如下

import java.util.Scanner;
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[][] dp = new int[n+1][n+1];for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++ )dp[i][j] = scanner.nextInt();//用dp数组去存储位置上的金币for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) {if(i == 1 && j == 1) dp[i][j] = dp[i][j]; else if(i == 1) dp[i][j] = dp[i][j-1] + dp[i][j];else if(j == 1) dp[i][j] = dp[i-1][j] + dp[i][j];else dp[i][j] = (Math.max(dp[i-1][j], dp[i][j-1]) + dp[i][j]);}}System.out.println(dp[n][n]);}
}

dp数组从二维降为一维

  • 关键在于一个理清时间的思维。
  • 初始化时,我们用dp数组去存储第一行各位置,能拿到的最大金币。
  • 在最后一个for循环中,实现了先搜索第i行中的最大金币数,在搜索第i+1行的效果。
    • 两种情况,当j==1时,dp[j] += gold[i][j],意味着上一行中的dp[j],加上位置上的金币数,等于这一行第j列拿到的最大金币数。
    • 否则dp[j] = Math.max(dp[j-1],dp[j]) + gold[i][j]。其中max函数中的dp[j-1]意味着从左边来的,也就是左边位置的最大金币数,与从上边来(上一行)的最大金币数去最大值,加上位置上的金币数。
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[][] gold = new int[n+1][n+1];int[] dp = new int [n+1];for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)gold[i][j] = scanner.nextInt();//初始化for(int j = 1; j <= n; j++) {if(j == 1) dp[1] = gold[1][j];else dp[j] = dp[j-1] + gold[1][j];}for(int i = 2; i <= n; i++) {for(int j = 1; j <= n; j++) {if(j == 1) dp[j] += gold[i][j];else dp[j] = Math.max(dp[j-1],dp[j]) + gold[i][j];}}System.out.println(dp[n]);}
}

 第二个方法貌似有时候过不了第九个评测样例,然后多测几次就能通过了,不知道是官方系统的问题还是。

 收获:

for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++ )num[i][j] = scanner.nextInt();

实现样例输入,看来java中隔一个空格后就会进行下一个变量的输入。

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

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

相关文章

【MCAL】MCU模块详解

目录 前言 正文 1. MCU模块介绍 2. MCU依赖的模块 3. MCU模块提供服务 3.1 时钟的初始化 3.2 MCU模式的配置 3.3 MCU软件复位功能 3.4 RAM的初始化 4.MCU重要数据类型 4.1 Mcu_ResetType 4.2 Mcu_ModeType 5. MCU重要API 5.1 Mcu_Init 5.2 Mcu_InitClock 5.3 M…

信息系统安全——Linux 访问控制机制分析

实验 4 Linux 访问控制机制分析 4.1 实验名称 《Linux 访问控制机制分析》 4.2 实验目的 1 、熟悉 Linux基本访问控制机制使用和原理 2 、熟悉 Linux S 位的作用和使用 3 、熟悉强制访问控制 Selinux 原理及其使用 4.3 实验步骤及内容 1 、Linux 基本访问控制机制 &#xff08…

vue el-table 多选框回填

主要代码: //选中列&#xff0c;所有列&#xff0c;表名toggleSelection(selectRows, totalRows, tablename) {this.$refs.table.clearSelection();if (selectRows.length > 0) {this.$nextTick(() > {selectRows.forEach(item > {totalRows.forEach(item1 > {if (…

C语言天花板——指针(经典题目)

指针我们已经学习的差不多了&#xff0c;今天我来给大家分享几个经典的题目&#xff0c;来让我们相互学习&#x1f3ce;️&#x1f3ce;️&#x1f3ce;️ int main() {int a[4] { 1, 2, 3, 4 };int* ptr1 (int*)(&a 1);int* ptr2 (int*)((int)a 1);printf("%x,%…

连锁品牌如何引流获客?小魔推短视频矩阵助你流量爆棚

近几年因为大环境的影响&#xff0c;大多数实体行业的生意都不太好做&#xff0c;为了帮助更多实体行业提升品牌知名度&#xff0c;带来更多的流量与转化&#xff0c;餐赞小魔推也在不断的更新迭代&#xff0c;同时考虑到了单门店与连锁品牌使用的便捷性。 目前针对连锁品牌方&…

功能权限篇

文章目录 1. 如何设计一套权限系统1.1 目标1.2 权限模型1.2.1 模型一RBAC1.2.2 模型二ABAC 2.如何实现菜单的创建&#xff1f;2.1 表结构2.2 前端实现2.3 后端实现 3. 如何实现角色的创建&#xff1f;4.如何给用户分配权限 —— 将菜单赋予角色&#xff1f;5.如何给用户分配权限…

【目标跟踪】跨相机如何匹配像素

文章目录 前言一、计算思路二、代码三、结果 前言 本本篇博客介绍一种非常简单粗暴的方法&#xff0c;做到跨相机像素匹配。已知各相机内外参&#xff0c;计算共视区域像素投影&#xff08;不需要计算图像特征&#xff09;。废话不多说&#xff0c;直接来&#xff0c;见下图。…

QT -狗狗管理工具

QT -狗狗管理工具 一、演示效果二、UML三、关键代码四、程序链接 一、演示效果 二、UML 三、关键代码 #include <QFrame> #include <QHBoxLayout> #include <QVBoxLayout> #include <QLabel> #include <QSizePolicy> #include <QDialog> …

算法第十八天-打家劫舍Ⅱ

打家劫舍Ⅱ 题目要求 解题思路 [打家劫舍Ⅱ]是说两个相邻的房间不能同时偷&#xff0c;并且首尾两个房间是相邻的&#xff08;不能同时偷首尾房间&#xff09;明显是基于[打家劫舍Ⅰ]做的升级。[打家劫舍Ⅰ]也是说两个相邻的房间不能同时偷&#xff0c;但是首尾房间不是相邻的…

Nas群晖中安装Cpolar实现内网穿透

1、到Cpolar官网中安装对应的套间 cpolar官网&#xff1a; cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站 2、到群晖nas中安装套间 选择好套间无脑下一步 已完成

时间序列数据的季节性检测

时间序列分析是统计学和数据科学的一个基本研究领域&#xff0c;它为理解和预测序列数据中的模式提供了一个强大的框架。特别是时间序列数据&#xff0c;它捕获连续时间间隔内的信息&#xff0c;使分析师能够揭示趋势&#xff0c;季节性模式和其他时间依赖性。在时间序列分析的…

GPT应用开发:运行你的第一个聊天程序

本系列文章介绍基于OpenAI GPT API开发应用的方法&#xff0c;适合从零开始&#xff0c;也适合查缺补漏。 本文首先介绍基于聊天API编程的方法。 环境搭建 很多机器学习框架和类库都是使用Python编写的&#xff0c;OpenAI提供的很多例子也是Python编写的&#xff0c;所以为了…

PTA(浙大版《C语言程序设计(第3版)》题目集

PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集 学习C语言程序设计的PTA题目 目录 PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集) 习题2-1 求整数均值 (10 分)输入格式:…

JS常用插件 Swiper插件 实现轮播图

Swiper介绍 Swiper 是一款免费以及轻量级的移动设备触控滑块的js框架 中文官网地址: https://www.swiper.com.cn/ 点击查看Swiper演示&#xff0c;里面的功能和样式十分丰富&#xff0c;根据自己的需求选择 中文教程中详细介绍了如何使用Swiper API文档中介绍了各个模块以及参…

如何画出优秀的系统架构图-架构师系列-学习总结

--- 后之视今&#xff0c;亦犹今之视昔&#xff01; 目录 早期系统架构图 早期系统架构视图 41视图解读 41架构视图缺点 现代系统架构图的指导实践 业务架构 例子 使用场景 画图技巧 客户端架构、前端架构 例子 使用场景 画图技巧 系统架构 例子 定义 使用场…

C++面试宝典第19题:最长公共前缀

题目 编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串""。说明:所有输入只包含小写字母a-z。 示例1: 输入: ["flower", "flow", "flight"]输出: "fl" 示例2: 输入: ["dog",…

微信小程序快速入门03

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java项目分享》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、生命周期生…

手写springBoot启动器

提示&#xff1a;springboot原理&#xff0c;手写springboot启动器&#xff0c;手写模拟SpringBoot启动过程、手写模拟SpringBoot自动配置功能 文章目录 前言一、本文内容1、手写模拟SpringBoot启动过程2、手写模拟SpringBoot自动配置功能 二、项目总体介绍三、代码实现(手写模…

python的库或函数不会用:使用help函数查看函数

help(time) # 查看time这个库 FUNCTIONS #函数&#xff1b;都可以调用asctime(...)asctime([tuple]) -> string #调用这个函数的参数需要一个元组&#xff08;tuple&#xff09;&#xff0c;->&#xff1a;代表返回值是string类型的#下面是简单的介绍Convert a time tup…

k8s的存储卷、数据卷---动态PV创建

当发布PVC之后可以生成PV&#xff0c;还可以在动态服务器上直接生成挂载目录。PVC直接绑定和使用PV。 动态PV需要两个组件 存储卷插件&#xff1a;Provisioner(存储分配器)根据定义的属性创建PV StorageClass&#xff1a;定义属性 存储卷插件 存储卷插件&#xff1a;k8s本…