使用Swift

时间:2018-05-08 21:22:47

标签: swift algorithm backtracking

我尝试使用回溯算法实现解决方案。

我有一些权重[1,2,7,10,20,70,100,200,700...],我希望在给定输入/

之后返回权重

例如input => 12应该返回[2,10] 例如input => 8应该返回[1,7]

我的代码似乎不能很好地运作。它仅适用于某些输入数字,例如138

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 //正确的重量

我希望你能帮助我,并解释我做错了什么。

2 个答案:

答案 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