PIPIOJ 1599 题解:PIPI 的数字游戏(完全背包最少个数)
题目链接:http://pipioj.online/problem.php?id=1599
题意重述
给定 n 个数字,每个数字可以被重复使用。
目标是凑出和为 m,问最少要用多少个数字;如果凑不出,输出 -1。
数据范围(单组):
1 <= n <= 5001 <= m <= 1000- 数字
x满足0 <= x <= 1000 - 多组测试
T <= 100
思路
这是标准的「完全背包求最少件数」。
定义 dp[s]:凑出和 s 所需的最少数字个数。
初始化:
dp[0] = 0- 其余
dp[s] = INF
转移(每个数字可重复使用):
dp[s] = min(dp[s], dp[s - x] + 1),其中 s >= x。
因为是“可重复使用”,所以同一个数字 x 时,s 要从小到大遍历。
最后:
dp[m]仍是INF,输出-1- 否则输出
dp[m]
时间复杂度 O(n * m),空间复杂度 O(m)。
C++17 代码
1 |
|
样例解释
输入:
1 | 2 |
- 第 1 组:
6 = 3 + 3,最少用2个 - 第 2 组:用
2和4不可能凑出3,所以是-1
易错点
- 这是“每个数字可重复选取”,不是 01 背包。
- 数字里可能有
0,对凑正数没有帮助,转移时可直接跳过。 - 多组数据下,每组都要重新初始化
dp。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 David's Blog!
评论