当前位置: 首页 > news >正文

蓝桥杯动态规划实战:从数字三角形到砝码称重

适合人群:蓝桥杯备考生 | 算法竞赛入门者 | DP学习实践者

目录

一、我的动态规划入门之路

1. 数字三角形:经典DP首战告捷

2. 砝码称重:背包问题的变形

二、蓝桥杯高频算法考点

三、蓝桥杯DP专项训练题

四、备考建议


一、我的动态规划入门之路

1. 数字三角形:经典DP首战告捷

题目描述

从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和(路径上的每一步只可沿左斜线向下或右斜线向下走)。

输入描述:
- 输入的第一行包含一个整数N(1≤N≤100),表示三角形的行数。
- 下面的N行给出数字三角形。
(数字三角形上的数都是0至99之间的整数。)

输出描述:
- 输出一个整数,表示答案。

解题思路:

我们可以先假象一个两层的三角形:

 1
2 3

这个时候是:1 -> 3 这时候1+3=4便是最大的路径。把这个三角形扩充到三层:

  6
 5 1
4 2 3

 此时6 -> 5 -> 4 这条路径是最大的了,但是当数字杂乱且层数多的时候就不方便找出来啦。

所以我们可以这样想,怎么把三层四层甚至多层的三角形变成两层三层的三角形。

1. 我们把最后两层换成一堆小三角形,并将最大的一个将在上一层上,如:

  6
 5 1
4 2 3
#################
 5     |  1
4 2    | 2 3

4->5最大;3->1最大。
故而三层的三角形可以简化为:
 6
9 4
这样便是两层的三角形了

也就是自底向上,代码如下

def db(li1,li2):
  for i in range(len(li1)):
    if li1[i] +li2[i] >= li1[i] +li2[i+1]:
      li1[i] += li2[i]
    else:
       li1[i] += li2[i+1]
  return li1

# 请在此输入您的代码
triangle = []
n = int(input())
# 读取每一行的数字
for i in range(n):
    row = list(map(int, input().split()))  # 将输入的字符串分割并转换为整数列表
    triangle.append(row)

# 问题处理
for k in range(n-1):
  x = db(triangle[n-1-k-1],triangle[n-1-k])
  triangle[n-1-k-1] = x

print(triangle[0][0])

2.  我们也可以把最顶层的数加到下一层,然后又将第二层加到第三层,在比较最后一层最大的数,如:

  6
 5 1
4 2 3

6->5  |  6->1
-------------------
 11  7
4  2  3

11->4,11->2  |  7->2,7->3
显然11>7,所以11和7都能达到的2应该选11

15 13 10 --> 15最大 

自顶向下的方法,代码如下

def main():
    import sys
    input = sys.stdin.read().split()
    idx = 0
    n = int(input[idx])
    idx += 1
    
    # 读取数塔的每一层
    arr = []
    for i in range(n):
        row = list(map(int, input[idx:idx+i+1]))
        arr.append(row)
        idx += i + 1
    
    # 初始化动态规划数组
    dp = [[0]*(i+1) for i in range(n)]
    dp[0][0] = arr[0][0]
    
    # 动态规划填表
    for i in range(1, n):
        for j in range(i+1):
            if j == 0:
                # 只能来自上一层的左边
                dp[i][j] = dp[i-1][j] + arr[i][j]
            elif j == i:
                # 只能来自上一层的右边
                dp[i][j] = dp[i-1][j-1] + arr[i][j]
            else:
                # 可以来自上一层的左边或右边,取最大值
                dp[i][j] = max(dp[i-1][j-1], dp[i-1][j]) + arr[i][j]
    
    # 找到最后一层的最大值
    max_val = max(dp[-1])
    print(max_val)

if __name__ == "__main__":
    main()

2. 砝码称重:背包问题的变形

题目描述:给定砝码重量,求能称出的不同重量数(蓝桥杯2021省赛题)。

解题思路:

天平分左右两边,我们假设左边放砝码减重量,右边是增;同时每一个砝码只能使用一次;砝码总重量不超过100000。

所以我们可以假定砝码之和为能得到的最大重量,初始时天平的重量为0;我们可以通过:

0 + 1 代表右边放砝码1的情况
0 - 1 代表左边放砝码1的情况
-------------------------------
1 + 3 代表右边放砝码1 + 砝码3的情况
1 - 3 代表右边放砝码1,左边放砝码3的情况

由于左右只差称出的重量是一致的,所以我们在出现负值时,可以用abd取绝对值转为正的,或者改为重的减轻的(3-1)来变换,代码如下:
代码片段

def bg(num_list):
    max_wight = sum(num_list)
    bag = [False] * (max_wight + 1) # 0~砝码总重的重量
    bag[0] = True # 称出初始为0

    for w in num_list:
        # 使用临时数组来避免重复更新
        new_bag = bag[:]
        for i in range(max_wight, -1, -1):
            if bag[i]:
                if i + w <= max_wight:
                    new_bag[i + w] = True
                if i - w >= 0:
                    new_bag[i - w] = True
                if w - i >=0:
                    new_bag[w - i] = True

        # 更新原数组为新的状态
        bag = new_bag
    # print(bag)
    # 计算所有可以表示的重量数量
    count = 0
    for i in range(max_wight + 1):
        if bag[i]:
            count += 1

    return count - 1  # 排除0这个状态

n = int(input())
num_list = list(map(int, input().split()))
result = bg(num_list)
num_list.sort(reverse=True)
# print(num_list)
print(result)
# 6 0
# 10 2 4 6 0
# 9 10 11 1 2 3 4 5 6 7 0

二、蓝桥杯高频算法考点

算法类型常见题型例题编号
贪心算法区间调度、最小生成树蓝桥杯2020省赛:合并果子
DFS/BFS迷宫问题、连通块计数蓝桥杯2019国赛:迷宫
并查集动态连通性、朋友圈问题蓝桥杯2021省赛:合根植物
前缀和子矩阵和、差分数组应用蓝桥杯2022省赛:统计子矩阵
二分查找最大值最小化、有序数据查找蓝桥杯2021国赛:分巧克力

三、蓝桥杯DP专项训练题

  1. 入门必刷

    • 数字三角形(经典DP)

    • 砝码称重(背包变形)

    • 跳跃(状态转移设计)

  2. 进阶挑战

    • 最大子阵和(二维前缀和+DP)

    • 乘积最大(高精度+区间DP)

    • 最少砝码(数学思维+DP)

四、备考建议

  1. 刷题策略

    • 按算法分类集中突破(如连续3天专攻DP)

    • 每道题记录错题本,分析状态转移设计误区

  2. 资源推荐

    • 官方题解:蓝桥杯题库

    • 算法模板:代码随想录

相关文章:

  • 波士顿咨询X大型制造业数字化转型战略规划项目(98页PPT)(文末有下载方式)
  • 知行之桥数据追踪实战指南:三种定位数据的精准方法
  • C++差分风暴:区间修改终极模板
  • SpringBoot实现发邮件功能+邮件内容带模版
  • 理解大模型的function call ,思维链COT和MCP 协议
  • H-ZERO自定义全局字体 支持项目个性化字体需求
  • 【WRF-Urban】城市冠层/建筑楼层设置
  • C++ 学习笔记(三)—— 入门+类和对象
  • MySQL 8主从复制配置最佳实践
  • uniapp 实现微信小程序电影选座功能
  • leetcode-50.Pow(x,n)
  • 火山云对比阿里云的优势在哪里
  • 【Linux操作系统——学习笔记二】Linux简单导航命令操作
  • 安徽建筑安全员A证考试的报名条件是什么?
  • spring boot 过滤器简单demo
  • Java实现字符串大写字母转小写的多种方法及优化策略
  • Web Component 教程(三):生命周期方法的触发时机与实际应用
  • 【C++】树和二叉树的实现(下)
  • 数据库:一文掌握 MongoDB 的各种指令(MongoDB指令备忘)
  • uniapp常用组件
  • 网友景区倒卖柠檬水3.5小时赚254元?蜜雪冰城:正核实
  • 区域、学校、课堂联动,上海浦东让AI素养培育贯穿基础教育全学段
  • 中国需加强自主创新和国际合作,提升产业链供应链韧性
  • 2025年新季夏粮收购量将达到2000亿斤左右
  • 新疆巴音郭楞州和硕县发生4.6级地震,震源深度10千米
  • 欧阳娜娜等20多名艺人被台当局列入重要查核对象,国台办回应