最近在刷蓝桥杯题目,按题目做一下笔记整理,顺便分享交流一下,有更好的解决方案欢迎大家共同提出探讨,以下源代码为系统提交满分答案
拿金币
问题描述
资源限制
Python时间限制:5.0s
问题描述
有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式
第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式
最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2
样例输出
11
数据规模与约定
n<=1000
源代码
n = int(input())
# 创建列表
dp = []
# 为列表添加数据
for i in range(n):
dp.append(list(map(int,input().split())))
# 计算边界值
for i in range(1,n):
dp[0][i] += dp[0][i-1]
dp[i][0] += dp[i-1][0]
# 计算其他数
for i in range(1,n):
for j in range(1,n):
dp[i][j] += max(dp[i-1][j],dp[i][j-1])
# 输出最后一位数,即最大金币数
print(dp[-1][-1])
问题分析
当我们看到题目的时候,可能大多数人想到了
每走一步判断右侧和下方的大小,哪大走哪
,这样走到最后就是最大数,但事实果真如此吗,我们用下面这个例子分析一下,图一(蓝)为我们所设想的走法,图二(黄)为最大的走法:
理想数据为38,而实际最大数据为49,通过比较,很显然,这路径不是金币最多的路径,可以看出这种做法比较浅显,无法看到较远的目标,有点像贪心算法。
该题为经典的DP(动态规划)问题,需要使用DP(动态规划)思想解决
什么是DP(动态规划)呢?
用非人话说,DP基本性质:
1、问题具有最优⼦结构性质:问题所包含的⼦问题的解也是最优的。
2、⽆后效性:算⼀步是⼀步,只会存储当前的运算结果。为下⼀步计算提供结果。
DP的解题核心:写出递归问题的转移⽅程并确定转移⽅程的边界条件。
用人话转述就是:一个问题可以被分解为诸多子问题,每一个求解结果都依赖于上一步的结果,同时在计算中需要注意边界值的判断
我们可以尝试将每个格子内的最大金币数计算出来
,这样当我们求到最后一个数时,最后一个数的值就是我们所要求的最大金币数的值。每个格子的最大金币数应该是左侧或上方最大数+格子本身数量
,如图示
通过图示同时我们注意到:
1.最左上角的数值无需计算
2.最左侧的数值仅依赖上侧数值,最上方的数值仅依赖左侧数值
3.其余数值均为max(左,上)+本身
当遍历计算完成后,右下角的数值即我们所求的最大金币数(二维列表中最后一个元素dp[-1][-1]
)
更多题目,点击查看👇
Python蓝桥杯 基础练习题目整理👈
Python蓝桥杯 算法训练题目整理👈
Python蓝桥杯 算法提高题目整理👈
Python蓝桥杯 历届真题题目整理👈
Python蓝桥杯 练习系统题目整理(全)👈