C++ 多约束背包
我试图解决以下问题: 输入:C++ 多约束背包,c++,algorithm,dynamic-programming,backtracking,knapsack-problem,C++,Algorithm,Dynamic Programming,Backtracking,Knapsack Problem,我试图解决以下问题: 输入: 项目数组,每个项目有3个不同的权重(整数),一个值和此类型项目的可用数量 每种重量的最大值 输出: 一个数组,它告诉您为了获得最大值,每个项目要取多少。每件物品的重量总和不得超过允许的最大值,并且您不得从可用物品中再拿走更多物品 示例输出:{3,0,2,1}表示项目1中的3个,项目2中的0个,项目3中的2个,以及项目4中的1个 示例场景: 如果我不太清楚这个解释,想象一下这是关于把食物放在背包上。每种食物都有重量、体积、热量和价值,每种食物都有一定量。目标是使背包中
{3,0,2,1}
表示项目1
中的3个,项目2
中的0个,项目3
中的2个,以及项目4
中的1个
示例场景:
如果我不太清楚这个解释,想象一下这是关于把食物放在背包上。每种食物都有重量、体积、热量和价值,每种食物都有一定量。目标是使背包中食物的价值最大化,而不超过一定的最大重量、体积和热量
在这种情况下,输入可以是:
Array<Food>:
数组:
- 汉堡(重量2,体积2,热量5,价值5美元,汉堡数量3)
- 比萨饼(重量3,体积7,热量6,价值8美元,比萨饼数量2)
- 热狗(重量1,体积1,热量3,值2$,热狗数量6)
int MaxWeight=10;int MaxVolume=15;int最大热量=10代码>
我的尝试
由于数据集非常小(比如说7种类型的物品,每个物品的可用物品不超过15件),我想到了暴力搜索:
- 跟踪到目前为止找到的最佳集合(最大值和不最大值)
超过任何限制),调用最佳设置B
- 有一个递归函数
R(s)
,它接受一个集合(每个项目的数量数组)作为输入,如果输入无效,它将返回。如果输入有效,它首先更新B(如果s
优于B),然后为每个产品p\i调用R(s+p\u i)
其思想是首先调用R(s),s=空集(每个产品为0),然后创建每个可能的分支,同时忽略超过权重的分支
这显然不起作用,因为需要检查的分支数量非常多,即使只有7项
非常感谢您的帮助在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;
}
之后,我们必须跟踪并查看哪些项目会带来最大价值。下一个方法将打印所需内容:
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;
}
}
}
void打印结果(int-ind、int-weight1、int-weight2、int-weight3){
if(ind==Array.size())返回;
int maxi=备忘录[ind][weight1][weight2][weight3];
对于(int i=0;你能提供一个输入示例吗?我不清楚“每种重量”的最大值是什么意思,或者你第一次输入的“值”是什么。@JustinRandall当然,我现在把它添加到问题中听起来你的算法应该更倾向于在不超过t的情况下将尽可能多的最高值项放入背包中如果你的唯一目标是价值最大化,他会限制你。从价值最高的物品开始,看看有多少合适。一直到价值较低的物品,直到你不能再合适为止。
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;
}
}
}