今天发现了一个可以很好解决背包问题的方法。
首先简要说明一下背包问题:给定一组物品,每个物品都有相应的价值以及总量,我们有一个背包,容量有限,如何在有限的容量中选择物品,让总价值最大。
通常我们的解决办法是使用动态规划来解决,具体如何解决这里就不阐述了,下面我给大家介绍一种更简单的方法:那就是or-tools!(免费、开源、支持java8)
首先定义物品信息:

在使用时需要创建模型:
ini
CpModel model = new CpModel();
然后创建线性表达式来合计重量和价值:
ini
LinearExprBuilder weightVar = LinearExpr.newBuilder();
```
LinearExprBuilder allPriceVar = LinearExpr.newBuilder();
```
接下来就是关键步骤,将每个物品信息(重量、价格)添加进来

接下就是添加约束条件
//总的重量必须小于背包允许的重量(maxWeight)
model.addLessOrEqual(weightVar,maxWeight);
再设定我们的求解目标(价值最大)
ini
model.maximize(LinearExpr.sum(new LinearArgument[]{allPriceVar}));
最后进行求解
scss
CpSolver solver = new CpSolver();
solver.getParameters().setMaxTimeInSeconds(60); // 60秒超时
solver.getParameters().setEnumerateAllSolutions(true);//找出所有的可行解
CpSolverStatus status = solver.solve(model);
是不是感觉很简单,我们不用再自己写循环进行来求解了,or-tools会不断的进行尝试找到最优的解。 以下是某次运行的结果

下面是完整的代码,有兴趣的小伙伴可以试着调整用不同的参数运行看看效果。
ini
import com.google.ortools.Loader;
import com.google.ortools.sat.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class BagProblemDemo {
static {
Loader.loadNativeLibraries();
}
public static void main(String[] args) {
//背包允许的最大重量
Integer maxWeight=100;
List<GoodInfo> goodsInfoList=getGoods();
// 2. 创建模型
CpModel model = new CpModel();
//目标,在有限的重量下,让价值最大
//创建重量的变量
LinearExprBuilder weightVar = LinearExpr.newBuilder();
//价值
LinearExprBuilder allPriceVar = LinearExpr.newBuilder();
for (GoodInfo goodInfo : goodsInfoList) {
//创建变量
BoolVar isPickVar = model.newBoolVar("is_pick_"+goodInfo.getGoodId());
goodInfo.setPickBool(isPickVar);
Integer price = goodInfo.getPrice();
Integer weight = goodInfo.getWeight();
Integer signelPrice=price*weight;
//添加价值信息
allPriceVar.addTerm(isPickVar,signelPrice);
//添加重量信息
weightVar.addTerm(isPickVar,weight);
}
model.addLessOrEqual(weightVar,maxWeight);
model.maximize(LinearExpr.sum(new LinearArgument[]{allPriceVar}));
CpSolver solver = new CpSolver();
solver.getParameters().setMaxTimeInSeconds(60); // 60秒超时
solver.getParameters().setEnumerateAllSolutions(true);//找出所有的可行解
CpSolverStatus status = solver.solve(model);
if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) {
System.out.printf("求解状态: %s\n", status);
System.out.printf("重量: %d\n", solver.value(weightVar));
System.out.printf("价值: %d\n", solver.value(allPriceVar));
for (GoodInfo goodInfo : goodsInfoList) {
System.out.println(goodInfo.toString());
if (solver.booleanValue(goodInfo.getPickBool())){
System.out.println("选中了"+goodInfo.getGoodName());
}
}
}else{
System.out.printf("无解");
}
}
private static List<GoodInfo> getGoods(){
List<GoodInfo> bagInfoList=new ArrayList<GoodInfo>();
for(int i=1;i<=10;i++){
GoodInfo goodInfo = new GoodInfo();
Integer wehgith=new Random().nextInt(50);
goodInfo.setWeight(wehgith);
Integer price=new Random().nextInt(60);
goodInfo.setPrice(price);
goodInfo.setGoodName("bag"+i);
goodInfo.setGoodId(i);
bagInfoList.add(goodInfo);
}
return bagInfoList;
}
}