Algorithm 仅使用超过阈值的指定面额硬币可获得的最小货币金额

Algorithm 仅使用超过阈值的指定面额硬币可获得的最小货币金额,algorithm,combinations,dynamic-programming,subset-sum,coin-change,Algorithm,Combinations,Dynamic Programming,Subset Sum,Coin Change,换句话说,给定一组n个正整数a和一个阈值B,我想找到最小的C,以便: C>B C=A[1]*k[1]+A[2]*k[2]+…+A[n]*k[n],k[i]是整数>=0 例如,如果A={6,11,16},那么我们可以得到的值是:{0,6,11,12,16,17,18,22,23,24,27,28,29,30,32…所以如果B=14那么C将是16,B=22C=23,B=18C=22 这个问题有以下限制:2

换句话说,给定一组n个正整数
a
和一个阈值
B
,我想找到最小的
C
,以便:

  • C>B
  • C=A[1]*k[1]+A[2]*k[2]+…+A[n]*k[n]
    k[i]
    是整数>=0
例如,如果
A={6,11,16}
,那么我们可以得到的值是:
{0,6,11,12,16,17,18,22,23,24,27,28,29,30,32…
所以如果
B=14
那么
C
将是
16
B=22
C=23
B=18
C=22

这个问题有以下限制:
2
0
1
(这就是我被卡住的原因)。您还必须为大小为
<1000
的数组
B
计算数组C(但这可能无关紧要)。该算法应在C++ 0.3秒以内运行。 这里描述的算法可以解决这个问题,但速度不够快:
我计算表格直到B+Amin,因为
Amin*k=B
然后问题不会改变(只需将+1添加到B中),我们可以这样问:如果我们有特定的硬币或钞票(无限多个),并且想用它们购买东西,那么我们可以支付多少钱,以便出纳员必须归还最小的零钱


我怀疑可能有帮助的事情:

如果最大公约数
(x,y)=1
,则任何高于
xy的值− x− 可以使用
x
y
获得y



编辑:添加了示例和注释。

我认为你无法获得比O(n*B)更好的结果,因为Frobenius数(在这个数之上,所有金额都可以用给定的面额构建)49999和49998比10^9大得多,你至少需要计算一些输入的最佳值。如果gcd(A)>1,则弗罗贝尼乌斯数不存在,但可以通过将所有A和B(向下舍入)除以gcd(A)并将得到的C乘以gcd(A)得到最终结果来防止这种情况

您的伪代码仍有很大的改进空间。您查看所有面额的次数几乎为B+Amin,并且多次将表中的值设置为true

标准实现将如下所示:

sort(A);
table[0] = true;
for (int i = A[0]; i <= B + A[0]; i++)
    for (int j = 0; j < n && A[j] <= i; j++)
        if (table[i - A[j]]) {
            table[i] = true;
            break;
        }
排序(A);
表[0]=真;

对于(int i=A[0];i您可以计算可以构建的连续金额的数量,如果它比最小的A少一个,您可以立即返回B+1。这个问题似乎确实相当于您链接的硬币问题(对于硬币面额中的一组互质数)。如果Frobenius数为,您也可以通过将所有A除以所有A和B的gcd(向下舍入),将解乘以所有A的gcd得到真实值。这样,您可以确保有一个点可以建立所有金额(无缺口),并且您还可以检查每个金额,如果(B-金额+1)%current A==0表示提前返回。顺便说一句,在您的算法中,一个可能的(不确定会涉及多少开销)优化如下:如果在任何时候您发现
Amin
连续的
true
元素,那么您可以在这些元素之后构建任何数字(根据维基百科章节中的推理)。还概述了W日志(W)解决方案。
sort(A);
table[0] = true;
for (int i = A[0]; i <= B + A[0]; i++)
    for (int j = 0; j < n && A[j] <= i; j++)
        if (table[i - A[j]]) {
            table[i] = true;
            break;
        }
table[0] = true;
for (int i = 0; i <= B + Amin; i++)
    if (table[i])
        for (j = 0; j < n; j++)
            if (i + A[j] <= B + Amin)
                table[i + A[j]] = true;