硬币更换程序使用动态编程背包,允许重复

时间:2016-03-10 13:15:28

标签: c dynamic-programming

我已经编写了以下代码来实现硬币更改问题:您将获得n种类型的硬币面值v(1)< v(2)< ......< v(n)(所有整数)。假设v(1)= 1,所以你可以随时改变任何金额C.给出一个算法,用尽可能少的硬币改变金额C.

我通过将每个硬币的所有值设置为-1来修改背包,重复允许问题。然后程序应该返回最大值,使得所需硬币(面额)的权重加到大小变量(所需的变化)。我无法想象我哪里出错了。我应该得到-2的回答,暗示我需要两个硬币,但我得到-1作为答案。代码:

#include <stdio.h>
#define max(a,b) (a > b ? a : b)

int matrix[100][100] = {0};

int knapsack(int index, int size, int weights[],int values[]){
    int take,dontTake;

    take = dontTake = 0;

    if (matrix[index][size]!=0)
        return matrix[index][size];

    if (index==0){
        if (weights[0]<=size){
            matrix[index][size] = values[0];
            return values[0];
        }
        else{
            matrix[index][size] = 0;
            return 0;
        }
    }

    if (weights[index]<=size) 
        take = values[index] + knapsack(index, size-weights[index], weights, values); //knapsack(index) and not //knapsack(index-1) 

    dontTake = knapsack(index-1, size, weights, values);

    matrix[index][size] = max (take, dontTake);

    return matrix[index][size];

}

int main(){
    int nItems = 4;
    int knapsackSize = 10;
    int weights[4] = {5,4,6,3};
    int values[4] = {-1,-1,-1,-1};

    printf("Max value = %dn",knapsack(nItems-1,knapsackSize,weights,values));

    return 0;
}

我哪里出错了,我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

这很简单,因为-1 > -2并且您在每个级别的2个选项之间取得最大值。

编辑:我已经提出了一个解决方案,其中值被视为正面,我也对代码进行了微小的更改,如果有些你不理解的东西可以随意询问。

#include <stdio.h>
#define min(a,b) (a < b ? a : b)
#define INF 10000000

int matrix[100][100] = {0};

int knapsack(int index, int size, int weights[],int values[]){
    int take = INF;

    if (index == -1){
        if(size == 0) return 0;
        else return INF;
    }

    if (matrix[index][size]!=-1)
        return matrix[index][size];

    for(int itemcount = 0;(itemcount * weights[index]) <= size;itemcount++){
        if ((weights[index] * itemcount) <= size) 
            take = min(take, (values[index] * itemcount) + knapsack(index - 1, size - (itemcount * weights[index]), weights, values)); //knapsack(index) and not //knapsack(index-1) 
    }

    matrix[index][size] = take;

    return matrix[index][size];

}

int main(){
    int nItems = 4;
    int knapsackSize = 10;
    int weights[4] = {5,4,6,3};
    int values[4] = {1,1,1,1};
    for(int i = 0;i < 100;i++) for(int j = 0;j < 100;j++) matrix[i][j] = -1;

    printf("Min value = %d\n",knapsack(nItems-1,knapsackSize,weights,values));

    return 0;
}

指向Ideone上的解决方案:http://ideone.com/TNycZo

这里我把无穷大作为一个大整数,找到最小值,如果答案是无穷大意味着无法创造这样的面额。