彩带切割
数据规模:,保证至少存在一种切法。
思路
设 表示恰好切出总长 的彩带时最多能得到的段数,切不出则为 。初始 (空彩带 zero 段),其余为 。
按长度从小到大转移:最后一段的长度 只能是 、、 之一,若 且 可被恰好拼出,则
三者都不可达时 保持 。题目保证 至少有一种切法,因此最终答案就是 。这等价于完全背包(每种物品无限件,最大化件数),背包容量恰好装满的写法。
复杂度
时间 (状态 ,每个状态枚举 3 种段长),额外空间 。
仓颉实现
查看仓颉实现
import std.env.*
import std.convert.*
main() {
let reader = getStdIn()
let v = reader.readln().getOrThrow().split(" ", removeEmpty: true).map({ p: String => Int64.parse(p) })
let n = v[0]
let cuts = [v[1], v[2], v[3]]
let dp = Array<Int64>(n + 1, { _ => -1 })
dp[0] = 0
var i: Int64 = 1
while (i <= n) {
var best: Int64 = -1
for (x in cuts) {
if (i >= x && dp[i - x] >= 0 && dp[i - x] + 1 > best) {
best = dp[i - x] + 1
}
}
dp[i] = best
i += 1
}
println(dp[n])
}