2014-06-17 28 views
0

Im试图通过回溯来解决背包问题。在C++中使用Backtraking的背包解决方案

例如,对于下面的值,背包函数将返回14作为解决方案,但正确的结果应该是7

int n = 3, weights[] = {2, 3, 1}, values[] = {6, 15, 7}; 

int solution = 0, max = 2; 


void Knapsack (int i, int max, int value, int *solution) 
{ 
    int k; 

    for (k = i; k < n; k++) { 
    if (weights[k] <= max) { 
     Knapsack (k, max - weights[k], value + values[k], solution); 

     if (value+ values[k] > *solution) 
     *solution= value + values[k]; 
    } 
    } 
} 

这里有什么问题?

+2

您是否尝试过使用一个非常小的问题(即更小的值[]')并逐步执行代码,直到您发现错误,然后思考为什么?或者,将一些'std :: cout << ...'行放入循环中? –

回答

2
#include<iostream> 
#include<vector> 

using namespace std; 

int weights[] = {2, 3, 1}, values[] = {6, 15, 7}; 

int solution = 0, n = 3; 

std::vector<int> vsol; 
std::vector<int> temp; 

bool issol; 


void Knapsack (int i, int max, int value) 
{ 
    for (int k = i; k < n; k++) { 
    if (max > 0) 
    { 
     if (weights[k] <= max) 
     { 
      temp.push_back(k); 
      if (value+ values[k] >= solution) 
      { 
      solution = value + values[k]; 
      issol = true; 
      } 
     } 
     if ((k+1) < n) 
     { 
      Knapsack (k+1, max - weights[k], value + values[k]); 
     } 
     else 
     { 
      if (issol == true) 
      { 
      if (! vsol.empty()) vsol.clear(); 
      std::move(temp.begin(), temp.end(), std::back_inserter(vsol)); 
      temp.clear(); 
      issol = false; 
      } else temp.clear(); 
      return; 
     } 
    } 
    else 
    { 
     if (issol == true) 
     { 
      if (! vsol.empty()) vsol.clear(); 
      std::move(temp.begin(), temp.end(), std::back_inserter(vsol)); 
      temp.clear(); 
      issol = false; 
     } else temp.clear(); 
     return; 
    } 
    } 
} 

int main() 
{ 
    Knapsack(0, 2, 0); 
    cout << "solution: " << solution << endl; 
    for(vector<int>::iterator it = vsol.begin(); it != vsol.end(); it++) 
     cout << *it << " "; 
    return 0; 
} 

当您再次调用Knapsack函数以将索引向前移动时,您需要将k增加1。

添加代码以打印解决方案的索引位置。如果存在多个解决方案(即总数相同),则只会打印出最后解决方案的位置。

+0

在这种情况下很容易保存解决方案的元素? – Wyvern666

+0

当然可以,你可以使用一个容器(数组或任何,最好是一个STL容器)来存储权重数组的索引位置(以及相应的值) – pipja

+0

在递归调用之前,正确的位置是做什么的? – Wyvern666