【问题标题】:Dynamic Programming - Minimum Coin caching动态规划 - 最小硬币缓存
【发布时间】:2016-02-03 17:22:02
【问题描述】:

之前我发布了question 关于硬币自动售货机问题(所需的最低硬币数量)。原来问题是 for 循环中的拼写错误,所以现在程序可以工作了。原来的问题是这样的:

作为自动售货机控制器的程序员,您需要计算构成返还客户所需零钱的最小硬币数量。这个问题的有效解决方案采用动态规划方法,首先计算 1 美分找零所需的硬币数量,然后是 2 美分,然后是 3 美分,直到达到所需的找零,并且每次都使用先前计算的硬币的数量。编写一个包含函数ComputeChange() 的程序,该程序获取有效硬币的列表和所需的零钱。该程序应反复从控制台请求所需的更改并相应地调用ComputeChange()它还应该使用“缓存”,其中保留任何先前计算的中间值以供后续查找。

问题是代码使用了递归,因此计算大值需要很长时间。使用缓存应该可以改善这个问题,但我不知道如何去做。代码可以在下面找到。

#include <stdio.h>
#include <limits.h>

int computeChange(int[],int,int);
int min(int[],int);

int main(){
    int cur[]={1,2,5,10,20,50,100,200};
    int n = sizeof(cur)/sizeof(int);
    int v;

    printf("Enter a value in euro cents: ");
    scanf("%d", &v);

    printf("The minimum number of euro coins required is %d", computeChange(cur, v, n));

    return 0;
}

int computeChange(int cur[], int v, int n){
    if(v < 0)
        return INT_MAX;
    else if(v == 0)
        return 0;
    else{
        int possible_mins[n], i;
        for(i = 0; i < n; i++){
            possible_mins[i]=computeChange(cur, v-cur[i], n);
        }
        return 1+min(possible_mins, n);
    };
}

int min(int a[], int n){
    int min = INT_MAX, i;
    for(i = 0; i < n; i++){
        if((a[i]>=0) && (a[i]< min))
            min = a[i];
    }
    return min;
}

【问题讨论】:

    标签: c caching dynamic-programming


    【解决方案1】:

    使用您现有的代码:

    #include <stdio.h>
    #include <limits.h>
    
    int computeChange(int[],int,int);
    int min(int[],int);
    void initChange ();
    int change [MAX]; //used for memoization
    
    
    
    int main(){
        int cur[]={1,2,5,10,20,50,100,200};
        int n = sizeof(cur)/sizeof(int);
        int v;
    
        initChange ();
        printf("Enter a value in euro cents: ");
        scanf("%d", &v);
    
        printf("The minimum number of euro coins required is %d", computeChange(cur, v, n));
    
        return 0;
    }
    
    void initChange () {
        int i =0;
        for (i = 0; i < MAX; i++) {
            change[i] = INT_MAX;
        }
    }
    
    int computeChange(int cur[], int v, int n){
        if(v < 0)
            return INT_MAX;
        else if(v == 0)
            return 0;
        else{
    
            if (change[v] == INT_MAX) {
                int possible_mins[n], i;
                for(i = 0; i < n; i++){
                    possible_mins[i]=computeChange(cur, v-cur[i], n);
                }
                change[v] = 1 + min(possible_mins, n); // memoization
            }
            return change[v];//you return the memoized value
    
        };
    }
    
    int min(int a[], int n){
        int min = INT_MAX, i;
        for(i = 0; i < n; i++){
            if((a[i]>=0) && (a[i]< min))
                min = a[i];
        }
        return min;
    }
    




    我已经在您之前的问题中发布了使用循环的解决方案。我会在这里再次发布:

    所以下面是使用记忆和动态编程解决您的问题的代码 sn-p。复杂度为 O(Val*numTypesofCoins)。

    最后,change[val] 会给你 val 的最小硬币数。

    int main (void) {
        int change [MAX];
        int cur[]={1,2,5,10,20,50,100,200};
        int n = sizeof(a)/sizeof(int);
        int val; //whatever user enters to get the num of coins required.
        printf("Enter a value in euro cents: ");
        scanf("%d", &val);
    
        for (i=0; i <= val; i++) {
            change[i] = INT_MAX;
        }
        for (i=0; i < n; i++) { // change for the currency coins should be 1.
            change[cur[i]] = 1;
        }
    
        for (i=1; i <= val; i++) {
            int min = INT_MAX;
            int coins = 0;
            if (change[i] != INT_MAX) { // Already got in 2nd loop
                continue;
            }
            for (j=0; j < n; j++) {
                if (cur[j] > i) { // coin value greater than i, so break.
                    break;
                }
                coins = 1 + change[i - cur[j]]; 
                if (coins < min) {
                    min = coins;
                }
            }
            change[i] = min;
    
        }
    }
    

    【讨论】:

    • 谢谢。 MAX 是什么?是INT_MAX吗?
    • 可以是任何允许用户输入的最大值。您还需要注意系统中的可用内存。或者,您可以在用户键入 v 的值后动态分配。在这种情况下,您不必担心浪费空间。在这种情况下:int * change; change = malloc (sizeof(int)*v);
    • 那么我要怎么做才能编译呢?它告诉我initChange 有冲突的类型
    • 看更新,忘记在main前声明了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 2023-03-20
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 2011-02-07
    相关资源
    最近更新 更多