打印背包解决方案

时间:2016-12-28 12:32:35

标签: c recursion knapsack-problem

我对背包问题有以下解决方案:(wt []是权重数组,val []是数值数组,n是数组大小,index是我们正在尝试的当前项(用于递归)和arr是一个数组,代表天气或不是我在解决方案中包含的项目。

int knapSack(int W, int wt[], int val[], int n, int index, int arr[])
{
   if (n == index || W == 0)
       return 0;
   if (wt[index] > W)
       return knapSack(W, wt, val, n, index+1 );

   int with=val[index]+knapSack(W-wt[index], wt, val, n, index+1);
   int without=knapSack(W, wt, val, n, index+1);

   if(with>without){
       arr[index]=1;
       return with;
   }
   else{
       arr[index]=0;
       return without;
   }

}

我试图在这个递归解决方案中打印所选项目,方法是将数组(res)中的索引的索引设置为1。 据我了解,如果with>without,则表示我选择当前项目或项目#index。那为什么这不会返回正确的价值呢? 我使用递归算法是有原因的,我知道使用memoization版本可以更容易。 例如:
重量:5 6 7 10 11
值:2 4 5 6 9
W = 25
将在数组res中返回5个。当解决方案为18时,项目2,3,5(从索引1开始)。

1 个答案:

答案 0 :(得分:3)

前提1 :在您的代码中,knapSack的递归调用未通过arr,这会导致编译错误,我认为它只是复制/粘贴错误。

前提2 :根据您提供的数据,生成的arr值并非全部1,而是01011,但仍然不正确

考虑假设情况,在执行功能期间,with大于without:在with计算期间arr填充了正确的值;但随后开始without计算,该计算将覆盖arr值。

由于with大于without,因此返回的arr将是错误的,这就是问题的原因。

一个简单的解决方法是复制arr计算返回的with,这样就不会被without计算覆盖,例如:

int with=val[index]+knapSack(W-wt[index], wt, val, n, index+1, arr);

// copy the "with" arr
int arrWith[n];
copyArr(arr, arrWith, n);

int without=knapSack(W, wt, val, n, index+1, arr);

if(with>without){
    // restore the "with" arr
    copyArr(arrWith, arr, n);

    arr[index]=1;
    return with;
}
else{
    arr[index]=0;
    return without;
}

copyArr只是:

void copyArr(int arr[], int arrDest[], int n) {
    int i;
    for(i = 0; i < n; i++) {
        arrDest[i] = arr[i];
    }
}

通过此修复,arr的结果值正确01101