【问题标题】:Coin sum with negative coin values负硬币值的硬币总和
【发布时间】:2014-07-26 09:15:07
【问题描述】:

我设法编写了这段代码来找到最小的硬币总和以达到准确的价值。但我写这篇文章是考虑到硬币的正值。

有人可以告诉我如何升级此代码以计算具有负硬币值的最小硬币总和吗? 提前谢谢!

int main()
{
 int arr[] = {1, 2, 3};
 int m = sizeof(arr)/sizeof(arr[0]);
 int n = 4;
 printf(" %d ", count(arr, m, n));
 return 0;
}


int count( int S[], int m, int n )
{
 int i, j, x, y;

 int table[n+1][m];

 for (i=0; i<m; i++)
    table[0][i] = 1;
  // Fill rest of the table enteries in bottom up manner
  for (i = 1; i < n+1; i++)
  {
    for (j = 0; j < m; j++)
    {
        // Count of solutions including S[j]
        x = (i-S[j] >= 0)? table[i - S[j]][j]: 0;
        // Count of solutions excluding S[j]
        y = (j >= 1)? table[i][j-1]: 0;
        // total count
        table[i][j] = x + y;
    }
}
return table[n][m-1];
}

【问题讨论】:

  • 首先,您是否意识到您当前的解决方案永远不允许多次选择同一个硬币?我提到这一点是因为在用硬币找零方面陈述的问题通常使用一组硬币类型,可以根据需要多次使用,而不是一组固定的硬币.
  • 其次,假设您想继续将问题视为一组硬币而不是硬币类型,我建议首先处理所有负硬币,然后“向下”构建:从概念上讲,您想为所有min &lt;= i &lt; 0 计算table[i][j],其中min 是所有负硬币的总和。 (当然你不能索引一个带有负下标的数组,所以你需要一些其他的方案,例如一个偏移量。)然后你可以像往常一样工作。
  • 什么是“负币值”?为什么在这里使用“硬币”这个词?

标签: algorithm dynamic-programming


【解决方案1】:

尚不清楚您是想任意次数地使用每个硬币(通常是这样说明问题的方式),还是您是否只想使用每个硬币 0 次或 1 次(这是您的代码所暗示的) .

如果允许您使用每个硬币任意次数,那么概念上最简单的解决方案可能是在编号为 0 到 N 的节点上构建一个图,其中 N 是所有硬币正值的总和,然后连接节点 i如果 (j-i) 是您的硬币值之一,则 j 具有有向边,然后运行 ​​Dijkstra 算法,其中所有边的权重为 1,以找到从 0 到图中所有其他节点的最短路径,这将包括您的目标值。您可以回溯以找到针对您的目标值的特定最佳解决方案。

如果您最多只能使用每个硬币一次,那么您可以不失一般性地假设给定目标值的最佳解决方案将首先使用所有正硬币,然后使用所有负硬币。因此,您可以使用广度优先搜索,使用所有正硬币(其中 N 是所有正硬币值的总和)为值 0 到 N 建立最佳解决方案,您可以在其中跟踪生成每个目标值所需的硬币数量和最优解中使用的最后一个硬币,然后排序正硬币,然后一次取一个硬币,并考虑将每个硬币添加到您当前可以获得的每个值中,看看您是否可以使用更少的数量获得一个新的值硬币。然后,在您仅使用正硬币计算出所有最优解之后,您对负值硬币进行排序,并类似地以相反的方向处理最优解数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2012-07-04
    • 1970-01-01
    • 2013-12-09
    • 2017-10-28
    相关资源
    最近更新 更多