我试图解决以下问题:
示例输出:{3,0,2,1}
表示item1
中的3个,item2
中的0个,item3
中的2个以及item4
中的1个。
如果我对解释不是很清楚,想象一下将食物放在背包上。每种类型的食物都具有重量,体积,卡路里数量和价值,并且每种类型的食物都有一定数量。目标是最大化背包中的食物价值,而不超过一定的最大重量,体积和卡路里。
在这种情况下, INPUT 可以是:
Array<Food>:
int MaxWeight = 10; int MaxVolume = 15; int MaxCalories = 10;
由于数据集非常小(比如7种类型的项目,并且每个项目不超过15件),我想到了一个强力搜索:
R(s)
,它接受一个集合(每个项目中有多少个数组)作为输入,如果输入无效,则返回。如果输入有效,则首先更新 B (如果s
优于 B ),然后为每个产品调用R(s + p_i)
p_i 我们的想法是首先使用s =空集(每个产品为0)调用R(s),并且将创建每个可能的分支,同时忽略超出权重的分支。
这显然没有用,因为即使只有少数7项,必须检查的分支数量也很大
非常感谢任何帮助!
答案 0 :(得分:2)
您必须在DP方法中考虑每种类型的重量。我将用C ++编写实现:
vector<Food> Array;
int memo[MAX_ITEM][MAX_WEIGHT1][MAX_WEIGHT2][MAX_WEIGHT3];
int f(int ind, int weight1, int weight2, int weight3){
if(weight1<0 || weight2<0 || weight3<0) return -INF;
if(ind == Array.size()) return 0;
int &ret= memo[ind][weight1][weight2][weight3];
if(ret>0) return ret;
int res = 0;
for(int i=0;i<=Array[ind].maxOfType;i++)
res = max(res, i * Array[ind].value + f(ind+1, weight1-i*Array[ind].weight1, weight2-i*Array[ind].weight2, weight3-i*Array[ind].weight3));
return ret = res;
}
DP函数是递归的,我们使用memoization来优化它。它返回我们可以得到的最大值。你可以通过以下方式来打电话:
f(0,MaxWeight1, MaxWeight2, MaxWeight3);
之后我们必须跟踪并查看哪些项目具有最大价值。 Next方法将打印您想要的内容:
void printResult(int ind, int weight1, int weight2, int weight3){
if(ind == Array.size()) return;
int maxi = memo[ind][weight1][weight2][weight3];
for(int i=0;i<=Array[ind].maxOfType;i++){
int cur = i * Array[ind].value + f(ind+1, weight1-i*Array[ind].weight1, weight2-i*Array[ind].weight2, weight3-i*Array[ind].weight3);
if(cur == maxi){
cout<<i<<", ";
printResult(ind+1, weight1-i*Array[ind].weight1, weight2-i*Array[ind].weight2, weight3-i*Array[ind].weight3);
break;
}
}
}
所有代码都经过测试并且运行良好。