题解:AcWing 3417 砝码称重
【题目来源】
AcWing:3417. 砝码称重 - AcWing题库
【题目描述】
你有一架天平和 \(N\) 个砝码,这 \(N\) 个砝码重量依次是 \(W_1,W_2,⋅⋅⋅,W_N\)。
请你计算一共可以称出多少种不同的正整数重量?
注意砝码可以放在天平两边。
【输入】
输入的第一行包含一个整数 \(N\)。
第二行包含 \(N\) 个整数:\(W_1,W_2,W_3,⋅⋅⋅,W_N\)。
【输出】
输出一个整数代表答案。
【输入样例】
3
1 4 6
【输出样例】
10
【核心思想】
-
问题分析:给定 \(N\) 个砝码,重量分别为 \(W_1, W_2, \dots, W_N\)。每个砝码可以放在天平左边(加重量)、放在天平右边(减重量)或不使用。求能称出的不同正整数重量个数。这是一个布尔型DP问题,关键在于每个砝码有三种状态选择。
-
算法选择:
- 布尔型二维DP:
f[i][j]表示前 \(i\) 个砝码是否能称出重量 \(j\)(true/false) - 三状态转移:不放(继承)、放左边(+W[i])、放右边(-W[i],用绝对值处理)
- 布尔型二维DP:
-
关键步骤:
- 计算总重量:
m = sum(W[i]),最大可称重量不超过总重量 - 初始化:
f[0][0] = true,表示0个砝码可以称出重量0 - 状态转移:对于第 \(i\) 个砝码,遍历所有可能的重量 \(j\)(\(0 \leq j \leq m\))
- 不放:
f[i][j] = f[i-1][j] - 放右边(对侧,相当于加在右边):若 \(j + W[i] \leq m\),则
f[i][j] |= f[i-1][j+W[i]] - 放左边(同侧,相当于减掉重量):
f[i][j] |= f[i-1][abs(j-W[i])]
- 不放:
- 统计答案:遍历所有正整数重量 \(j\)(\(1 \leq j \leq m\)),若存在某个 \(i\) 使
f[i][j] == true,则重量 \(j\) 可达,ans++
- 计算总重量:
-
时间/空间复杂度:
- 时间复杂度:\(O(N \times m)\),其中 \(m = \sum W[i]\) 为所有砝码总重量
- 空间复杂度:\(O(N \times m)\),二维布尔数组
-
布尔型DP(天平放置)的核心思想:
- 三状态选择:每个砝码有三种选择,本质是01背包的扩展
- 重量范围覆盖:由于重量可能通过减法产生(放右边),DP表覆盖了从0到总重量 \(m\) 的范围
- 绝对值处理:使用
abs(j-W[i])处理减法后的非负重量 - 统计策略:检查每个重量是否在任意前 \(i\) 个砝码时可达
- 适用于"天平称重"、"正负选择"类问题
【解题思路】

【算法标签】
01背包
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 105, M = 100005; // 定义最大物品数N和最大总重量M
int n, m; // 物品数量n,总重量m
int w[N]; // 每个物品的重量
bool f[N][M]; // 动态规划数组,f[i][j]表示前i个物品能否称出重量j
int main() // 主函数
{
cin >> n; // 输入物品数量
for (int i=1; i<=n; i++) // 读取每个物品的重量
{
cin >> w[i]; // 输入第i个物品的重量
m += w[i]; // 累加总重量
}
f[0][0] = 1; // 初始状态:0个物品可以称出重量0
for (int i=1; i<=n; i++) // 遍历每个物品
for (int j=0; j<=m; j++) // 遍历所有可能的重量
{
f[i][j] = f[i-1][j]; // 不使用第i个物品
if (j+w[i]<=m) // 如果将物品放在对侧(加在右边)
{
f[i][j] |= f[i-1][j+w[i]]; // 可以从j+w[i]转移过来
}
f[i][j] |= f[i-1][abs(j-w[i])]; // 如果将物品放在同侧(减掉重量)
}
int ans = 0; // 可称出的不同重量数
for (int j=1; j<=m; j++) // 遍历所有可能的重量
for (int i=0; i<=n; i++) // 遍历所有物品数
if (f[i][j]) // 如果该重量可以被称出
{
ans++; // 计数加1
break; // 跳出内层循环
}
cout << ans << endl; // 输出可称出的不同重量数
return 0; // 程序正常结束
}
【运行结果】
3
1 4 6
10
浙公网安备 33010602011771号