参考: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 + '}'; } } }