十二届蓝桥杯 砝码称重(python)

本文探讨了蓝桥杯竞赛中的一道动态规划题目,涉及砝码称重的计数问题。通过逐个添加砝码,计算可以称出的不同重量,详细阐述了动态规划的实现思路,并提供了样例输入及解题过程。目前解法已通过部分测试用例,寻求优化建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 动态规划三大题型:计数问题、最值问题、存在性问题。

该题问可以称出多少种不同的重量,属于计数题型。

动态规划实现思路

从一个砝码开始,每个状态列举出当前可以被称出的重量;每次加入一个砝码,这时只需要将上一个状态的每个可以被称出的重量与新的砝码进行组合,即得出当前砝码数量可以被称出的所有重量;一直到最后一个砝码加入,最后一个状态就得出了所有可以被称出的重量

样例输入:3  1  4  6

加入第一个砝码1(状态1)       只能称出重量1

加入第二个砝码4 (状态2)        自身4可以称出        在1的状态1下更新1+4=5,4-1=3,就是1,3,4,5;

加入第三个砝码6          自身6可以称出        在状态2下更新1+6=7,6-1=5,3+6=9,6-3=3,4+6=10,6-4=2,5+6=11,6-5=1,就是1,2,3,4,5,6,7,9,10,11;

 

number = int(input())  # 砝码数量
arr = list(map(int, input().split()))
summ = sum(arr)
# 动态规划数组  dp[i][j]代表加入第i个砝码时,能不能称出重量j
dp = [[False for l in range(summ + 1)] for h in range(number + 1
### 蓝桥杯砝码称重问题的C++解法 #### 问题描述 砝码称重问题是经典的动态规划或状态转移问题之一。给定一组不同重量的砝码,目标是计算可以组合出的不同总重量的数量。 以下是基于动态规划的思想实现的一个完整的解决方案: --- #### 动态规划思路解析 该问题可以通过二维布尔数组 `f[i][j]` 来表示前 `i` 个砝码能否组成重量 `j` 的情况。具体来说: - 如果第 `i` 个砝码不参与,则继承上一个状态:`f[i][j] = f[i - 1][j]`; - 如果第 `i` 个砝码放在左侧托盘,则考虑减少其重量的情况:`f[i][j] |= f[i - 1][abs(j - w[i])]`; - 如果第 `i` 个砝码放在右侧托盘,则增加其重量:`f[i][j] |= f[i - 1][j + w[i]]`. 最终统计所有可能的正整数重量即可得出答案[^2]。 --- #### 完整代码实现 以下是一个标准的 C++ 实现方案: ```cpp #include <iostream> #include <vector> using namespace std; const int N = 110, M = 2e5 + 10; bool f[N][M]; int w[N]; int main() { int n; cin >> n; // 输入砝码数量 int m = 0; for (int i = 1; i <= n; ++i) { cin >> w[i]; // 输入每个砝码的重量 m += w[i]; // 计算最大可能重量 } // 初始化 dp 数组 f[0][0] = true; // 填充 dp 表格 for (int i = 1; i <= n; ++i) { for (int j = 0; j <= m; ++j) { f[i][j] = f[i - 1][j]; // 不选当前砝码的状态 if (j >= w[i]) // 放入右侧托盘 f[i][j] |= f[i - 1][j - w[i]]; if (j + w[i] <= m) // 放入左侧托盘 f[i][j] |= f[i - 1][j + w[i]]; } } // 统计可组成的正整数重量数目 int ans = 0; for (int i = 1; i <= m; ++i) { if (f[n][i]) ans++; } cout << ans << endl; // 输出结果 return 0; } ``` 上述代码通过三维压缩的方式实现了动态规划表填充过程,并利用布尔变量记录每种重量的可能性。 --- #### 关键点说明 1. **初始化条件**: 初始状态下只有当没有任何砝码时能够构成零重量,即 `f[0][0] = true`. 2. **状态转移方程**: 对于每一个砝码,分别处理三种可能性(忽略、加入右盘、加入左盘),并更新对应位置的状态。 3. **边界控制**: 防止越界访问,在调整索引时需注意权重范围约束. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值