func closestCost(baseCosts []int, toppingCosts []int, target int) int {
x := baseCosts[0]
for _, c := range baseCosts {
x = min(x, c)
}
// 如果最小基础价格就已经超过 target,直接返回它
if x > target {
return x
}
// can[i] 表示是否可以恰好凑出价格 i(i <= target)
can := make([]bool, target+1)
// ans 用来记录超过 target 的最小可行价格
ans := 2 * target - x
// 把所有不超过 target 的基础价格标记为 true
for _, c := range baseCosts {
if c <= target {
can[c] = true
} else {
// 更新大于 target 的最小值
ans = min(ans, c)
}
}
// 对于每种配料,最多可以选 2 次
for _, c := range toppingCosts {
for count := 0; count < 2; count ++ {
for i := target; i > 0; i -- {
// 如果原来可以凑出 i,再加上当前配料 c 超过 target,就更新 ans
if can[i] && i + c > target {
ans = min(ans, i + c)
}
// 如果 i - c >= 0,并且之前能凑出 i - c,那么现在也可以凑出 i
if i - c > 0 {
can[i] = can[i] || can[i - c]
}
}
}
}
// 在不超过 target 的范围内,寻找最接近 target 的价格
// i 代表与 target 的差值,从小到大遍历
for i := 0; i <= ans - target; i ++ {
if can[target -i] {
// 找到最接近但不超过 target 的值,直接返回
return target - i
}
}
// 如果所有不超过 target 的组合都不够接近,则返回第一个超过 target 的最小值
return ans
}