基于面额,为特定价格支付的算法可能金额(超过)

时间:2010-06-05 17:40:59

标签: algorithm language-agnostic math currency

在当前项目中,人们可以订购送货上门的商品,并选择“付款时付款”作为付款选项。为了确保交付人员有足够的变化,客户被要求输入他们将支付的金额(例如,交付是48,13,他们将支付60, - (3 * 20, - ))。现在,如果它取决于我,我会把它变成一个自由的领域,但是已经决定应该是基于可用面额的选择,而不给出会导致一组面额可能更小的金额。

示例:

denominations = [1,2,5,10,20,50]
price = 78.12
possibilities:
    79  (multitude of options),
    80  (e.g. 4*20)
    90  (e.g. 50+2*20)
    100 (2*50)

它是国际性的,所以面额可能会改变,算法应该基于该列表。

我最接近的似乎有效:

for all denominations in reversed order (large=>small)
    add ceil(price/denomination) * denomination to possibles
    baseprice = floor(price/denomination) * denomination;
    for all smaller denominations as subdenomination in reversed order
        add baseprice + (ceil((price - baseprice) / subdenomination) * subdenomination) to possibles
    end for
end for
remove doubles
sort

似乎可以工作,但是在经过各种紧凑算法的尝试之后就出现了这种情况,我无法为为什么保护它起作用,这可能导致一些优势 - 案例/新国家选择错误,并确实产生了大量的双打。

因为这可能不是一个新问题,而谷歌等人。无法为我提供答案除了计算如何进行精确更改的大量页面之外,我想我会问:你之前解决了这个问题吗?哪种算法?任何证据都会一直有效吗?

2 个答案:

答案 0 :(得分:2)

它是贪婪算法的应用http://mathworld.wolfram.com/GreedyAlgorithm.html(一种用于从最小可能的组成部分递归构造一组对象的算法)

伪代码

list={1,2,5,10,20,50,100} (*ordered *)
while list not null
   found_answer = false
   p = ceil(price) (* assume integer denominations *)
   while not found_answer
      find_greedy (p, list) (*algorithm in the reference above*)
      p++
   remove(first(list))

编辑>一些迭代是无意义的>

list={1,2,5,10,20,50,100} (*ordered *)
p = ceil(price) (* assume integer denominations *)
while list not null
   found_answer = false
   while not found_answer
      find_greedy (p, list) (*algorithm in the reference above*)
      p++
   remove(first(list))

编辑>

我发现由于Pearson对Greedy算法的改进。其O(N ^ 3 log Z),其中N是面额数,Z是该集合中最大的账单。

您可以在http://library.wolfram.com/infocenter/MathSource/5187/

中找到它

答案 1 :(得分:0)

您可以在数据库中生成所有可能的付费硬币和纸张组合(英语不是很好),每行包含此组合的总和。

拥有这个数据库,您可以通过一个查询简单地获得所有可能的过度支付,

WHERE sum >= cost and sum <= cost + epsilon

关于epsilon的一些话,嗯..你可以从成本价值中分配它吗?也许10%的成本+ 10美元?:

WHERE sum >= cost and sum <= cost * 1.10 + 10

表格结构必须包含表示硬币数量和纸张类型的列数。 每列的值包含此类付费项目的出现次数。

这不是这个问题的最佳和最快的解决方案,但实现简单易行。 我想更好地解决这个问题。


您可以从costcost + epsilon的其他方式,并为每个值计算每个值的最小可能付费项目数。我有它的算法。您可以使用此算法执行此操作,但这是在C ++中:

int R[10000];
sort(C, C + coins, cmp);

R[0]=0;

for(int i=1; i <= coins_weight; i++)
{
    R[i] = 1000000;
    for (int j=0; j < coins; j++) 
    {
        if((C[j].weight <= i) && ((C[j].value + R[i - C[j].weight]) < R[i]))
        {
            R[i] = C[j].value + R[i - C[j].weight];
        }
    }
}

return R[coins_weight];

<击>