如果成本与使用每个数字相关联,则找出最大数量

时间:2013-09-27 16:33:12

标签: algorithm dynamic-programming memoization knapsack-problem greedy

我得到了我的总钱。现在我知道记下每个数字(1到9)所需的成本。那么如何创建最大数量呢?这个问题有没有动态编程方法?

示例:

可用总金额= 2
每个数字的成本(1到9)= 9, 11, 1, 12, 5, 8, 9, 10, 6
输出:33

3 个答案:

答案 0 :(得分:2)

这是根据 Bernhard Baker's 答案提出的算法实现的代码。 这个问题是我在Providence Health Services进行的hackerank考试中提出的。

    total_money = 2   
    
    cost_of_digit = [9, 11, 1, 12, 5, 8, 9, 10, 6]
    
    # Appending the list digits with [weight, number] 
    k=1
    digits=list()
    
    for i in cost_of_digit:
        digits.append([i,k])
        k+=1
    
    #  Discarding any digits that cost more than a bigger digit: (because it's never a good idea to pick that one instead of a cheaper digit with a bigger value)
    i = 8
    while(i>0):
        if digits[i][0] <= digits[i-1][0]:
            del digits[i-1]
            i-=1
        else:
            i-=1
    
    # Sorting the digits based on weight
    digits.sort(key=lambda x:x[0],reverse=True)
    
    max_digits = total_money//digits[-1][0] # Max digits that we can have in ANSWER
    selected_digit_weight = digits[-1][0] 
    
    ans=list()
    
    if max_digits > 0:
        for i in range(max_digits):
            ans.append(digits[-1][1])
    
    # Calculating extra money we have after the selected digits
    extra_money = total_money % digits[-1][0]
    
    index = 0
    
    # Sorting digits in Descending order according to their value
    digits.sort(key=lambda x:x[1],reverse=True)
    
    while(extra_money >= 0 and index < max_digits):
        temp = extra_money + selected_digit_weight # The money we have to replace the digit
        swap = False # If no digit is changed we can break the while loop 
        
        for i in digits:
            # Checking if the weight is less than money we have AND the digit is greater than previous digit
            if i[0] <= temp and i[1] > digits[-1][1]: 
                ans[index] = i[1]
                index += 1
                extra_money = temp - i[0]
                swap = True
                break
        if(not swap):
            break
    
    if len(ans) == 0:
        print("Number cannot be formed")
    else:
        for i in ans:
            print(i,end="")
        print()

答案 1 :(得分:1)

我认为您不需要动态编程,只需执行以下操作:

  • 尽可能多地选择成本最低的数字。
  • 现在您有一个号码(仅包含一种数字)。
  • 用您能承受的最大数字替换第一个数字
  • 如果你还有钱,那么第二次和第三次都要这样做,依此类推,直到你没钱了。

为什么会这样:

考虑11111&gt; 999991111&gt; 88888,或者说,最好是:

  • 选择尽可能多的数字,这是通过选择最便宜的数字来完成的。
  • 然后用你能承受的最高值数字替换左边的这些数字(这总是比选择几个更贵的数字更好)。

<强>优化

为了有效地做到这一点,丢弃任何花费超过更大数字的数字:(因为选择那个数字而不是价值更高的更便宜的数字绝不是一个好主意)

Given:
9, 11, 1, 12, 5, 8, 9, 10, 6
Removing all those where I put an X:
X, X, 1, X, 5, X, X, X, 6
So:
1, 5, 6

现在你可以对它进行二进制搜索(只记得哪个数字来自哪个数字)(尽管只有9位数字,二进制搜索并不真正为已经很小的运行时间创造奇迹)。

运行时间:

O(n)(有或没有优化,因为9是常数)

答案 2 :(得分:0)

解析Knapsack problem

  • 费用=数字费用
  • 值=数字编号(9优于1)

然后按数字递减排序。