java 实现穷举算法

这篇博客主要介绍如何使用Java实现穷举算法来生成对象的所有可能组合,特别是当有n个物品时,组合数量为2^n。通过遍历0到2^n的二进制字符串,可以得到每种组合,从而找到最优解。文章提供了具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://blog.youkuaiyun.com/changyuanchn/article/details/51417796

题目
/**
 * 
 * [0-1背包问题]有一个背包,背包容量是M=150kg。有7个物品,物品不可以分割成任意大小。
 * 要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
 * 物品 A    B    C   D    E    F    G
 * 重量 35kg 30kg 6kg 50kg 40kg 10kg 25kg
 * 价值 10   40   30  50   35   40   30
 */

其核心主要是如何穷举对象,对象有多少种组合排列,通过所有组合排列,遍历组合计算出最优的解

 

1.对象有多少种组合,一共有 n个物品 组合数量:C(0,n),C(1,n),C(2,n),……C(n-2,n),C(n-1,n),C(n,n) = 2^n

2.java 如何生成2^n种组合,参考https://blog.youkuaiyun.com/changyuanchn/article/details/51417796的实现,下列java代码中 genPowerSet 方法可得出组合,核心是通过0到2^n的二进制字符串遍历,可得每种组合,

3.计算出最优解

下面直接贴代码

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Algorithm {
    public static void main(String[] args) {
        List<List<Greedy>> lists = greedyAlgorithm();//多个相同结果
        for(List<Greedy> l : lists){
            System.out.println("最优解组合:" + l);
        }
    }
    /**
     * 贪婪算法
     * [0-1背包问题]有一个背包,背包容量是M=150kg。有7个物品,物品不可以分割成任意大小。
     * 要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
     * 物品 A    B    C   D    E    F    G
     * 重量 35kg 30kg 6kg 50kg 40kg 10kg 25kg
     * 价值 10   40   30  50   35   40   30
     */
    public static List<List<Greedy>> greedyAlgorithm(){
        String[] nameArr = new String[]{"A","B","C","D","E","F","G"};
        int[] weightArr =new int[]{35,30,6,50,40,10,25};
        int[] valueArr =new int[]{10,40,30,50,35,40,30};
        //一共有   7个物品 组合C(0,7),C(1,7),C(2,7),C(3,7),C(4,7),C(5,7),C(6,7),C(7,7) = 2^7
        List<Greedy> list = new ArrayList<>();
        for(int i=0;i<nameArr.length;i++){
            Greedy g = new Greedy();
            g.setName(nameArr[i]);
            g.setWeight(weightArr[i]);
            g.setValue(valueArr[i]);
            list.add(g);
        }
        List<List<Greedy>> lists = genPowerSet(list);
        int maxValue = 0;
        List<Integer> indexList = new ArrayList<>();//记录下标
        for(int i=0;i<lists.size();i++){
            int v = 0;//最优解价值
            int w = 0;//最优解质量
            for(Greedy g:lists.get(i)){
                v += g.getValue();
                w += g.getWeight();
            }
            if(w > 150){
                continue;
            }
            if(v > maxValue){
                indexList.add(i);
                maxValue = v;
            }
        }
        //不排除最大价值是相等的  质量不一样 或者品种不一样
        //提取质量最轻
        int value = lists.get(indexList.get(indexList.size()-1)).stream().mapToInt(Greedy::getValue).sum();//最优价值
        int weight = lists.get(indexList.get(indexList.size()-1)).stream().mapToInt(Greedy::getWeight).sum();;//最后一条的质量
        int j = indexList.size()-2;
        List<Integer> resultIndex = new ArrayList<>();
        resultIndex.add(indexList.get(indexList.size()-1));
        do{
            if(j<0){
                break;
            }
           int v = 0;
           int w = 0;
           for(Greedy g : lists.get(indexList.get(j))){
               v += g.getValue();
               w += g.getWeight();
           }
            if( value > v){
                break;
            }else if(v == value ){
                if(w == weight){//并列
                    resultIndex.add(j);
                }else if(w < weight){//质量小于上一条
                    resultIndex.clear();
                    resultIndex.add(j);
                }
            }
            j--;
        }while (true);
        return resultIndex.stream().map(e -> lists.get(e)).collect(Collectors.toList());
    }

    public static List<List<Greedy>> genPowerSet(List<Greedy> list){
        List<List<Greedy>> resList = new ArrayList<>();
        int maxNum = (2 << (list.size()-1));
        for(int i=0;i<maxNum;i++){
            List<Greedy> dataList =new ArrayList<>();
            String binstr = toBinaryString(i,list.size());
            for(int j=0;j<binstr.length();j++){
                if("1".equals(binstr.toCharArray()[j]+"")){
                    dataList.add(list.get(j));
                }
            }
            resList.add(dataList);
        }
        return resList;

    }

    //数字转换成二进制  n不足numDigitals位数时,前面补0
    //例 toBinaryString(3,10)   ->     0000000011
    public static String toBinaryString(int n,int numDigitals){
        String s = Integer.toBinaryString(n);
        if(s.length()<numDigitals){
            StringBuffer sb = new StringBuffer();
            for(int i=0;i<numDigitals-s.length();i++){
                sb.append("0");
            }
            sb.append(s);
            return sb.toString();
        }
        return s;

    }




    static class Greedy{
        private String name;
        private int weight;
        private int value;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getWeight() {
            return weight;
        }

        public void setWeight(int weight) {
            this.weight = weight;
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "Greedy{" +
                    "name='" + name + '\'' +
                    ", weight=" + weight +
                    ", value=" + value +
                    '}';
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值