开源算法or-tools运用之背包问题

今天发现了一个可以很好解决背包问题的方法。

首先简要说明一下背包问题:给定一组物品,每个物品都有相应的价值以及总量,我们有一个背包,容量有限,如何在有限的容量中选择物品,让总价值最大。

通常我们的解决办法是使用动态规划来解决,具体如何解决这里就不阐述了,下面我给大家介绍一种更简单的方法:那就是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;
    }
}
相关推荐
间彧3 分钟前
InfluxDB详解与应用实战
后端
间彧8 分钟前
对比InfluxDB与Prometheus在监控场景下的特点及选型建议
后端
间彧38 分钟前
面向切面编程(AOP)中的“通知”和 专门用于增强 Spring MVC 中控制器(Controller)的“通知”
后端
逻极42 分钟前
Rust数据类型(下):复合类型详解
开发语言·后端·rust
星释42 分钟前
Rust 练习册 12:所有权系统
开发语言·后端·rust
间彧43 分钟前
AOP中的五种通知类型在实际项目中如何选择?举例说明各自的典型应用场景
后端
间彧44 分钟前
Spring Boot中很多Advice后缀的注解和类,都是干什么的
后端
披着羊皮不是狼1 小时前
Spring Boot——从零开始写一个接口:项目构建 + 分层实战
java·spring boot·后端·分层
Tony Bai2 小时前
Go GUI 开发的“绝境”与“破局”:2025 年现状与展望
开发语言·后端·golang
Tony Bai2 小时前
【Go模块构建与依赖管理】08 深入 Go Module Proxy 协议
开发语言·后端·golang