递归解决背包问题

xiaoxiao2025-04-11  14

问题描述:有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的方案,使得选中物品的总重量不超过指定的限制重量,但选中的物品总价值最大。揭解法描述:采用递归寻找物品的寻找方案。设前面已有多种选择方案,并保留其中总价值最大的方案与一个数组option[]中,该方案的总价值存于变量maxval中,当前正在考虑新方案,其物品选择情况存于数组cop[]中。假设当前方案已经考虑了前i-1件物品,现在要考虑第i件物品;当前方案已包含的物品中良之和为tw;至此,若其余物品都选择是可能的话,本方案能到达的中间值得期望为tv。算法引入tv是当一旦当前方案的总价值的期望也小于前面方案的总价值maxval时,继续考察当前方案变成无意义的工作,应终止当前方案,立即去考察下一方案。因为当前方案的总价值不比maxval大时,该方案不会再被考虑,这同时保证函数后找到的方案一定会比前面的方案好。对于第i件物品的选择考虑有两种情况:(1):考虑物品 i 被选择,这种可能性仅当包含他不会超过总重量限制时才是可行的。选中后,继续递归去考查其余物品的选择。(2):考虑物品 i 不被选择,这种可能性仅当不包含物品 i 也有可能找到价值更大的方案的情况。

代码:

#include<iostream> using namespace std; struct bag { int weight; //包的重量 int value; //包的价值 }arr[100]; int option[100]; //用于保存满足的最大值方案 int cop[100]; //用于标识每个包是否被选取 int maxv, limitw, totv; int n; void find(int i, int tw, tv) { int k; if(tw + arr[i].weight <= limitw) //该包被选取 { cop[i] = 1; //设立标记 if(i < n - 1) { find(i + 1, tw + arr[i].weight, tv); //递归判断下一个包 } else { for(k = 0; k < n; k++) { option[k] = cop[k]; //保存包被选取的信息 } maxv = tv; //获取最大价值 } cop[i] = 0; //还原cop数组 } if(tv - arr[i].value > maxv) //该包没有被选取,判断该方案的价值是否最大。如果不是,继续寻找下一个包 { if(i < n - 1) { find(i + 1, tw, tv - arr[i].value); } else { for(k = 0; k < n; k++) { option[k] = cop[k]; //保存包被选取的信息 } maxv = tv - arr[i].value; //获取最大价值 } } } int main() { int k, w, v; cout << "please input count:"; cin >> n; totv = 0; for( k = 0; k < n; k++) { cout << "please input the weight and val" << endl; cin >> arr[k].weight; cin>> arr[k].value; } cout << "please input limitw:"; cin >> limitw; maxv = 0; for(k = 0; k < n; k++) { cop[k] = 0; } find(0, 0, totv); cout << "the result is:"; for(k = 0; k < n; k++) { if(option[k]) { cout << k + 1 << " "; } } cout << endl; cout << "the total value is:" << maxv << endl; return 0; }
转载请注明原文地址: https://www.6miu.com/read-5028026.html

最新回复(0)