我尝试使用回溯算法实现解决方案。
我有一些权重[1,2,7,10,20,70,100,200,700...]
,我希望在给定输入/
例如input => 12
应该返回[2,10]
例如input => 8
应该返回[1,7]
我的代码似乎不能很好地运作。它仅适用于某些输入数字,例如13
或8
for targetValue in [13] {
var currentValue = 0
var usedWeights: [Int] = []
for weight in weights {
if targetValue > weight {
currentValue += weight
usedWeights.append(weight)
} else if weight > targetValue {
let rememberLast = usedWeights.last ?? 0
usedWeights.remove(at: usedWeights.count-1)
currentValue -= rememberLast
if currentValue > targetValue || currentValue < targetValue {
let last = usedWeights.remove(at: usedWeights.count-1)
currentValue -= last
usedWeights.append(rememberLast)
currentValue -= rememberLast
print(usedWeights) /// [1, 2, 10] Yeah it work's :) but only for some number ..:(
}
}
}
}
使用的重量应该是唯一的。
找到重量我有点麻烦。
这就是算法的工作原理
输入=&gt; 13
1
1 + 2
1 + 2 + 7
1 + 2 + 7 + 10 // currentValue现在是20
1 + 2 + 7 //仍然没有解决方案获取最后删除的元素并删除当前的最后一个元素
1 + 2 + 10 //正确的重量
我希望你能帮助我,并解释我做错了什么。
答案 0 :(得分:1)
这是一个解决方案。通过权重反向迭代。如果重量小于或等于当前总重量,请使用重量。
let weights = [1,2,7,10,20,70,100,200,700] // the weights you have
let needed = 12 // The total weight you want
var total = needed // The current working total
var needs = [Int]() // The resulting weights needed
for weight in weights.reversed() {
if weight <= total {
needs.append(weight)
total -= weight
}
}
if total == 0 {
print("Need \(needs) for \(needed)")
} else {
print("No match for \(needed)")
}
答案 1 :(得分:0)
我不知道你如何设定重量。 但请考虑:
[2,3,6,10,20]
and needed = 21
然后算法找不到它(不匹配),当有明显的解决方案时:2 + 3 + 6 + 10
所以,你应该在搜索算法失败后递归调用,从你选择的第一个中删除权重。
这不是很干净,但似乎有效(在代码中,游乐场有些问题)
func searchIt(weightsSearch: [Int], neededSearch: Int) -> (needs: [Int], remainingWeights: [Int], found: Bool) {
var total = neededSearch // The current working total
var needs = [Int]() // The resulting weights needed
var remaining = weightsSearch
var firstNotYetSelected = true
var position = weightsSearch.count - 1
for weight in weightsSearch.reversed() {
if weight <= total {
needs.append(weight)
total -= weight
if firstNotYetSelected {
remaining.remove(at : position)
}
firstNotYetSelected = false
position -= 1
}
}
return (needs, remaining, total == 0)
}
var needs = [Int]() // The resulting weights needed
var remainingWeights = weights
var foundIt: Bool
repeat {
(needs, remainingWeights, foundIt) = searchIt(weightsSearch: remainingWeights, neededSearch: needed)
if foundIt {
print("Need \(needs) for \(needed)")
break
} else {
print("No match yet for \(needed)")
}
} while remainingWeights.count >= 1
与测试用例
let weights = [2,3,6,10,20]
let needed = 21
我们得到了
No match yet for 21
Need [10, 6, 3, 2] for 21
如果您想要所有解决方案,请通过continue替换break语句。
使用测试用例
let weights = [2,3,6,10,15,20]
let needed = 21
我们得到了2个解决方案
No match for 21
No match for 21
Need [15, 6] for 21
Need [10, 6, 3, 2] for 21
No match for 21
No match for 21
No match for 21