动态编程 - 最小硬币缓存

时间:2016-02-03 17:22:02

标签: c caching dynamic-programming

早些时候我发布了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;
}

1 个答案:

答案 0 :(得分: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;
}




我已经在上一个问题中使用循环发布了一个解决方案。我会在这里再次发布:

以下是使用memoization和动态编程解决问题的代码段。复杂性为O(Val * numTypesofCoins)。

最后,更改[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;

    }
}
相关问题