每种硬币只有一种可用时的修改硬币交换问题

给定一整套面额和一个总数,我们必须找到使总数准确所需的最小硬币数。

约束:每种面额只有一个硬币。

您如何比较贪婪方法和动态编程方法?

编辑: 示例:我有面额为1,2,3,5的现金。每个面额的硬币我只有一个。我想使用最少的硬币数获得11个零钱。答案是4(1 + 2 + 3 + 5)。如果每种面额都有无限量供应,答案将是3(5 + 5 + 1或5 + 3 + 3)。

xiaoqi176 回答:每种硬币只有一种可用时的修改硬币交换问题

找到任何解决方案,更不用说最大的解决方案了,称为subset sum problem。它是NP完全的,最有效的已知算法是exponential running time

因此,贪婪算法无法解决此问题。您不会比某种backtracking search做得更好。使用动态编程的解决方案实际上将等同于回溯搜索,只是实现方式有所不同。因此,比较非常短:贪婪不起作用,但动态编程可以。

,

您如何将贪婪方法与动态编程方法进行比较?

贪婪的方法在您的情况下将失败,因为您将永远不知道何时跳过或拿硬币来获得最佳答案。您必须通过包含/排除每个硬币来尝试所有可能的解决方案。

例如,您可以使用相同的硬币更改算法,通过动态编程来做到这一点,但避免多次取同一枚硬币

从上到下的递归方法:

int n = 4,k = 11;
int dp[4][12],coins[] = {1,2,3,5};

int solve(int i = 0,int sm = k) {
    // base case for when the sum is reached
    if (sm == 0) {
        return 0;
    }
    // took more than needed coins or reached the end without reaching sum
    if (sm < 0 || i == n) {
        return 1000000000;
    }
    // check if dp value already calculated
    int& ret = dp[i][sm];
    if (~ret) {
        return ret;
    }
    // otherwise,try taking the coin or skipping it
    return ret = min(solve(i+1,sm),1 + solve(i+1,sm-coins[i]));
}
int main() {
    memset(dp,-1,sizeof dp);
    cout << solve() << endl;
 return 0;
}
// output: 4
本文链接:https://www.f2er.com/3079494.html

大家都在问