zoukankan      html  css  js  c++  java
  • 【算法设计与分析基础】8、背包问题

    package cn.xf.algorithm.ch03;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import org.junit.Test;
    
    /**
     * 
     * 功能:背包问题的穷举办法
     * @author xiaofeng
     * @date 2017年5月4日
     * @fileName NPHardProblem.java
     *
     */
    public class NPHardProblem {
    
    	/**
    	 * 穷举
    	 * @param capacity  背包容量
    	 * @param worths	价值.
    	 * @return
    	 */
    	public long backPack(int capacity, List<Long> worths) {
    		 return 0l;
    	}
    	
    	/**
    	 * 网上办法
    	 * @param set
    	 * @param index
    	 * @return
    	 */
    	public static ArrayList<ArrayList<Integer>> getSubsets(ArrayList<Integer> set, int index) {
    		ArrayList<ArrayList<Integer>> allsubsets;
    		if (set.size() == index) {
    			allsubsets = new ArrayList<ArrayList<Integer>>();
    			allsubsets.add(new ArrayList<Integer>()); // empty set
    		} else {
    			allsubsets = getSubsets(set, index + 1);
    			int item = set.get(index);
    			ArrayList<ArrayList<Integer>> moresubsets = new ArrayList<ArrayList<Integer>>();
    			for (ArrayList<Integer> s : allsubsets) {
    				ArrayList<Integer> newSubset = new ArrayList<Integer>();
    				newSubset.addAll(s);
    				newSubset.add(item);
    				moresubsets.add(newSubset);
    			}
    			allsubsets.addAll(moresubsets);
    		}
    		return allsubsets;
    	}
    	
    	/**
    	 * 网络上的办法
    	 * @param set
    	 * @return
    	 */
    	public static ArrayList<ArrayList<Integer>> getSubsets2(ArrayList<Integer> set) {
    		ArrayList<ArrayList<Integer>> allsubsets = new ArrayList<ArrayList<Integer>>();
    		int max = 1 << set.size(); // how many sub sets
    		for (int i = 0; i < max; i++) {
    			int index = 0;
    			int k = i;
    			ArrayList<Integer> s = new ArrayList<Integer>();
    			while (k > 0) {
    				if ((k & 1) > 0) {
    					s.add(set.get(index));
    				}
    				k >>= 1;
    				index++;
    			}
    			allsubsets.add(s);
    		}
    		return allsubsets;
    	}
    	
    	/**
    	 * 求一个数组的所有集合,递归,
    	 * 递归终止条件:当前子集的个数达到参数要求
    	 * @param n
    	 * @param datas
    	 * @param setNum
    	 * @param resultSet
    	 */
    	public void subsetErr(List<Integer> datas, int index, List<Set<Integer>> resultSet){
    		if(datas.size() == index){
    			return;
    		}
    		//求当前设置子集的个数的全部
    		Set<Integer> curSubset = new HashSet<Integer>();
    		for(int i = 0; i < datas.size(); ++i){
    			//遍历所有以index索引开头的子集
    			if(i < index)
    				continue;
    			
    			//获取当前子集合,重新加入一个新的
    			curSubset.add(datas.get(i));
    			resultSet.add(curSubset);
    			Set<Integer> curSubset2 = new HashSet<Integer>();
    			curSubset2.addAll(curSubset);
    			curSubset = curSubset2; //替换为一个新的索引
    		}
    		subsetErr(datas, index + 1, resultSet);
    	}
    	
    	/**
    	 * 获取所有数据的子集
    	 * @param datas
    	 * @param index
    	 * @param curSubset
    	 * @return
    	 */
    	public static List<List<Integer>> subset(List<Integer> datas, int index, List<Integer> curSubset) {
    		List<List<Integer>> resultSet = new ArrayList<List<Integer>>();
    		
    		if(datas.size() == index){
    //			resultSet.add(curSubset);
    			return resultSet;
    		}
    		//循环递归所有的当前集合的下一个元素
    		for(int i = index; i < datas.size(); ++i){
    			List<Integer> curSubset2 = new ArrayList<Integer>();
    			curSubset2.addAll(curSubset);
    			//当前集合的最后有个元素
    			int curLastEleIndex = -1;
    			if(curSubset.size() > 0)
    				curLastEleIndex = datas.indexOf(curSubset.get(curSubset.size() - 1));
    			//当前集合的最后一个元素的序号不能比当前循环的数据的序号小
    			if(i <= curLastEleIndex)
    				continue;
    			//入股是后面的元素,吧值添加进入集合
    			curSubset2.add(datas.get(i));
    			resultSet.add(curSubset2);
    			//这个时候需要新建一个当前集合的复制对象进行拷贝
    			//获取递归后续的集合
    			resultSet.addAll(subset(datas, index + 1, curSubset2));
    		}		
    		return resultSet;
    	}
    	
    	@Test
    	public void npResult(){
    		List<Integer> datas = new ArrayList<Integer>();
    		datas.add(1);datas.add(2);datas.add(3);datas.add(4);
    		List<Integer> zhongliang = new ArrayList<Integer>();
    		zhongliang.add(7);zhongliang.add(3);zhongliang.add(4);zhongliang.add(5);
    		List<Integer> jiazhi = new ArrayList<Integer>();
    		jiazhi.add(42);jiazhi.add(12);jiazhi.add(40);jiazhi.add(25);
    		//列出所有可能集
    		int index = 0;
    		List<List<Integer>> resultSet = new ArrayList<List<Integer>>();
    		List<Integer> curSubset = new ArrayList<Integer>();
    		NPHardProblem np = new NPHardProblem();
    		resultSet = np.subset(datas, index, curSubset);
    		
    		//获取所有集合的总价值
    		List<List<Integer>> resultOkSet = new ArrayList<List<Integer>>();
    		List<Integer> allWorths = new ArrayList<Integer>();
    		for(List<Integer> oneSet : resultSet){
    			//获取子集总重量
    			int allzl = 0;
    			//价值
    			int alljz = 0;
    			for(int one : oneSet){
    				allzl += zhongliang.get(one - 1);
    				alljz += jiazhi.get(one - 1);
    			}
    			//重量不能超过背包10
    			if(allzl <= 10){
    				resultOkSet.add(oneSet);
    				allWorths.add(alljz);
    			}
    		}
    		//所有满足条件的子集选项
    		for(List s : resultOkSet){
    			System.out.println(s + " <====> " + allWorths.get(resultOkSet.indexOf(s)));
    		}
    //		System.out.println(resultOkSet);
    	}
    	
    	@Test
    	public void test0() {
    		List<Integer> datas = new ArrayList<Integer>();
    		datas.add(1);datas.add(2);datas.add(3);datas.add(4);datas.add(5);
    		int index = 0;
    		List<Set<Integer>> resultSet = new ArrayList<Set<Integer>>();
    		List<Integer> curSubset = new ArrayList<Integer>();
    		NPHardProblem np = new NPHardProblem();
    		np.subsetErr(datas, index, resultSet);
    		for(Set s : resultSet){
    			System.out.println(s);
    		}
    	}
    	
    	
    	@Test
    	public void test1() {
    		List<Integer> datas = new ArrayList<Integer>();
    		datas.add(1);datas.add(2);datas.add(3);datas.add(4);
    //		datas.add(4);datas.add(3);datas.add(2);datas.add(1);
    		int index = 0;
    		List<List<Integer>> resultSet = new ArrayList<List<Integer>>();
    		List<Integer> curSubset = new ArrayList<Integer>();
    		NPHardProblem np = new NPHardProblem();
    		resultSet = np.subset(datas, index, curSubset);
    		for(List s : resultSet){
    			System.out.println(s);
    		}
    	}
    	
    	@Test
    	public void test3() {
    		ArrayList<Integer> datas = new ArrayList<Integer>();
    		datas.add(1);datas.add(2);datas.add(3);datas.add(4);datas.add(4);
    //		datas.add(4);datas.add(3);datas.add(2);datas.add(1);
    		int index = 0;
    		ArrayList<ArrayList<Integer>> resultSet = new ArrayList<ArrayList<Integer>>();
    		List<Integer> curSubset = new ArrayList<Integer>();
    		NPHardProblem np = new NPHardProblem();
    		resultSet = np.getSubsets(datas, 0);
    		for(List s : resultSet){
    			System.out.println(s);
    		}
    	}
    	
    	/**
    	 * 获取这个集合的所有子集的个数,不包括空集
    	 * @param nums 单元个数
    	 * @return
    	 */
    	public long getSubsetCount(int nums){
    		int len = nums; //总个数
    		long result = 0;	//个数和
    		for(int i = 0; i < len; ++i) {
    			int fenzi = 1; //分子
    			int fenmu = 1; //当前分母
    			for(int j = 0, k = 1; j < i; ++j) {
    				fenzi *= (len - j);  //获取对应的伪阶乘,去掉j以下的数据
    				for(; k <= j; ++k){
    					fenmu *= (k + 1); //获取j的阶乘
    				}
    			}
    			//获取对应的C41,C42,C43,C44=4 + 6 + 4 + 1
    			result += fenzi / fenmu;
    		}
    		
    		return result;
    	}
    	
    	@Test
    	public void test2(){
    		NPHardProblem nphp = new NPHardProblem();
    		System.out.println(nphp.getSubsetCount(4));
    	}
    	
    }
    

      

    结果:

    求子集:

    test1:

    背包问题

    npResult

  • 相关阅读:
    nginx系列11:负载均衡哈希算法ip_hash与hash模块
    nginx系列10:通过upstream模块选择上游服务器和负载均衡策略round-robin
    nginx系列9:HTTP反向代理请求处理流程
    css 滚动条样式
    Vue优化:常见会导致内存泄漏问题及优化
    vue自定义指令导致的内存泄漏问题解决
    vue动态绑定class的几种方式
    前端知识点回顾之重点篇——CSS中flex布局
    Javascript数组操作
    pc端常用电脑屏幕 ((响应式PC端媒体查询)电脑屏幕分辨率尺寸大全)
  • 原文地址:https://www.cnblogs.com/cutter-point/p/6838497.html
Copyright © 2011-2022 走看看