背包问题

一,0-1背包;

问题描述:给定n个物品和一个背包。物品 i 的重量为 v[ i ],价值为w[ i ]。背包的容量为m。问如何装载才能使得装入背包中的物品总价值最大?

问题分析:在选择装入背包的时候。可以有两种选择:装入或者不装入。
设f[ i ] [ j ] 表示只看前i个物品,体积是j的情况下的总价值最值。
讨论:
不装入第i个物品:f[ i ] [ j ] = f [ i-1] [ j ];
装入第i个物品:f [ i ] [ j ] = f[ i-1 ] [ j-v [ i ] ];

代码分析:

public class 零一背包 {
     static int weight [] = {0,2,3,4,5};
     static int value [] = {0,3,4,5,6};
     static int [][]dp = new int [5][9];
     static int object[]= new int [5];
     public static void Dynamic(){   //动态规划下查找背包所能装载的最大价值
    	 int res = 0;
    	 for(int i = 1 ; i < 5 ; i ++) {
    		 for(int j = 0 ; j < 9 ; j ++) {
    			 if(weight[i] > j)
    				 dp[i][j] = dp[i-1][j];
    			 else
    				 dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]);
    		 }
    			for(int k = 1;k < 9;k ++) {
    				res = Math.max(res, dp[4][k]);
    			}  			
    	 }
    	 System.out.println("背包所能装的最大价值:"+res);
    	 System.out.println("该背包的二维数组为:");
    	 for(int r = 1; r < 5; r ++) {
    		 for(int s = 1; s < 9; s ++) {
    			 System.out.print(dp[r][s]+" ");
    		 }
    		 System.out.println();
    	 }
     }
	public static void find(int i , int j) {

		if(i == 0) {
		return ;
		}
		
		 if(dp[i][j] == dp[i-1][j])
		{
			object[i] = 0;
			find(i-1,j);
		}
		else if( dp[i][j] !=  dp[i-1][j]){
			object[i] = 1;
			find(i-1,j-weight[i]);
			System.out.println("第"+i+"个物品被装入");
		}
	}
	public static void main (String []args) {
		Dynamic();
		find (4,8);
	}
}

背包优化
上述背包问题是二维数组,可以把它进行优化为一维数组,但是在Dynamic方法中,一个 dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]);这个代码中后面的 dp[i-1][j-weight[i]]+value[i]中的i-1不能被正确表示,所以便不能进行正向从小到大遍历,得是从大到小遍历。
代码如下:

public class 零一优化 {
	static int weight [] = {0,2,3,4,5};
    static int value [] = {0,3,4,5,6};
    static int []dp = new int [9];

   public static void main(String[] args) {
   	 for(int i = 1 ; i < 5 ; i ++) {
   		 for(int j = 8 ; j >= weight[i] ; j --) {
   			
   				 dp[j] = Math.max(dp[j], dp[j-weight[i]]+value[i]);
   				 System.out.print(dp[j]+" ");
   		 }
   		 System.out.println();
      }
   	 System.out.println("最优解为:"+dp[8]);
}
}

二,完全背包;

完全完全背包问题是指每种物品都有无限件,可以在背包允许的范围内放入某种物品无限次以求最大价值。
代码如下:

import java.util.*;
//每种物品可以无限选择
public class 完全背包 {
	static int N = 1000; 
	 public static void main(String args[]){
	        Scanner in = new Scanner (System.in);
	        int f[] = new int [N];
	        int n = in.nextInt();
	        int m = in.nextInt();
	        for(int i = 1; i <= n; i ++ ) {
	        	int v = in.nextInt();
	        	int w = in.nextInt();
	        	for(int j = v; j <= m; j ++ ) {
	        		f[j] = Math.max(f[j], f[j-v]+w);
	        	}
	        }
	        System.out.println(f[m]);
	    } 
}

三,多重背包;

多重背包是指每种背包装入的物品有规定的数量,然后进行装入背包;
代码如下:

import java.util.Scanner;

//每种物品有限次选择
public class 多重背包 {
	static int N = 110; 
	 public static void main(String args[]){
	        Scanner in = new Scanner (System.in);
	        int f[] = new int [N];
	        int n = in.nextInt();//物品种类
	        int m = in.nextInt();//背包重量
	        for(int i = 1; i <= n; i ++ ) {
	        	int v = in.nextInt(); //物品重量
	        	int w = in.nextInt();//物品价值
	        	int s = in.nextInt();	//物品个数
	        for(int j = m; j >= 0; j --) {	        	
	        	for(int k =1; k <= s && k * v<=j; k ++ ) {
	        		f[j] = Math.max(f[j], f[j-k*v]+k*w);
	        	}
	        }
	    }
	        System.out.println(f[m]);
	    } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值