周围有很多硬币更换问题和答案,但我找不到这个问题,我想知道它是否甚至是硬币更换问题。
基本上我有一堆不同的硬币,每枚硬币都是无限量的。
所以说有各种面额的堆栈。每个堆栈都是无限的。 (如此无限数量的25c硬币,无限数量的2c硬币等)。
然而,在每堆硬币的顶部是一个特殊的硬币,其价值大于(或等于)下面的硬币。如果不在顶部使用这枚硬币,我就无法访问下面的硬币。
我想要解决的是获得一定金额所需的最小硬币数量。
我认为这是可解决的动态编程,但我不确定如何将此限制添加到传统解决方案中。
我想知道在使用它之后是否应该删除列表中的特殊硬币并将其替换为普通硬币,但我似乎无法推断是否会破坏算法。
答案 0 :(得分:0)
看起来像是一个经典的动态编程问题,其中的挑战是正确选择状态。
通常,我们选择所选硬币的总和作为问题状态,并选择所选硬币的数量作为状态值。过渡是我们可以采取的每一个可能的硬币。如果我们有25c和5c硬币,我们可以从具有值Count的状态Sum移动到状态Sum+25,count+1
和Sum+5,count+1
。
为了您的限制,州应该增加有关哪些特殊(顶部)硬币被采取的信息。所以你为每堆硬币添加一点。然后你只需要定义每个状态的可能转换。这很简单:如果设置了堆栈的位,则意味着已经采用了顶部硬币,您可以将该堆栈中的非顶级硬币添加到状态求和,保持所有位相同。否则,您可以从该堆栈中取出顶部硬币,将其值与状态求和相加,并设置相关位。
从状态开始,总和为0,所有位清零,值为0,然后从最低总和到目标构建状态。
最后,您应该遍历所有可能的位组合。将状态值与目标总和和位组合进行比较。选择最低 - 这将是答案。
示例解决方案代码:
#Available coins: (top coin value, other coins value)
stacks = [(17,8),(5,3),(11,1),(6,4)]
#Target sum
target_value = 70
states = dict()
states[(0,0)] = (0,None,None)
#DP going from sum 0 to target sum, bottom up:
for value in xrange(0, target_value):
#For each sum, consider every possible combination of bits
for bits in xrange(0, 2 ** len(stacks)):
#Can we get to this sum with this bits?
if (value,bits) in states:
count = states[(value,bits)][0]
#Let's take coin from each stack
for stack in xrange(0, len(stacks)):
stack_bit = (1 << stack)
if bits & stack_bit:
#Top coin already used, take second
cost = stacks[stack][1]
transition = (value + cost, bits)
else:
#Top coin not yet used
cost = stacks[stack][0]
transition = (value + cost, bits | stack_bit)
#If we can get a better solution for state with sum and bits
#update it
if (not (transition in states)) or states[transition][0] > count + 1:
#First element is coins number
#Second is 'backtrack reference'
#Third is coin value for this step
states[transition] = (count+1, (value,bits), cost)
min_count = target_value + 1
min_state = None
#Find the best solution over all states with sum=target_value
for bits in xrange(0, 2 ** len(stacks)):
if (target_value,bits) in states:
count = states[(target_value,bits)][0]
if count < min_count:
min_count = count
min_state = (target_value, bits)
collected_coins = []
state = min_state
if state == None:
print "No solution"
else:
#Follow backtrack references to get individual coins
while state <> (0,0):
collected_coins.append(states[state][2])
state = states[state][1]
print "Solution: %s" % list(reversed(collected_coins))
答案 1 :(得分:0)
以下解决方案基于两个事实 1)所有可用面额中的无限数量的硬币
Algorithm:-
Let Given number be x
call the below method repeatedly until you reach your coin value,
Each time of iteration pass the remaining value to be assigned with coins and also the coin denomination
Method which will receive the number and the coin value
Parameters: x - coin to be allocated
z - value of coin
if(x > z) {
integer y = x/z * z
if(y == x) {
x is divisible by z and hence allocate with x/z number of coins of z value.
}
if(Y != x) {
x is not a multiple of z and hence allocate with x/z number of coins from z cents value and then for remaining amount repeat the same logic mentioned here by having the next greatest denomination of
coin.
}
}
else if(x < z) {
return from this method;
}
else if(x == z) {
x is divisible by z and hence allocate with x/z number of coins of z value
}
Example iteration:
Given number = 48c
Coins denomination: 25c, 10c, 5c, 2c, 1c
First Iteration:
Parameter x = 48c and z = 25c
return value would be a map of 1 coin of 25c, [25c , 1]
calculate the remaining amount 48c - 25c = 23c
23c is not equal to zero and not equal to 1 continue the loop.
Second Iteration:
Parameter x = 23c and z = 10c
return value would be a map of 2 coins of 10c, [10c, 2]
calculate the remaining amount 23c - 20c = 3c
3c is not equal to zero and not equal to 1 continue the loop.
Third Iteration:
Parameter x = 3c and z = 5c
No coins allocated
3c is not equal to zero and not equal to 1 continue the loop.
Fourth Iteration:
Parameter x = 3c and z = 2c
return value would be a map of 1 coin of 2c, [2c, 1]
Remaining amount 3c - 2c = 1c
Remaining amount Equals to 1 add an entry in map [1c, 1]
Final Map Entries:
[25c, 1]
[10c, 2]
[2c, 1]
[1c, 1]
[1c, 1]