01背包问题

问题描述:假定背包的最大容量为W,N件物品,每件物品都有自己的价值和重量,将物品放入背包中使得背包内物品的总价值最大。可以参考链接:

https://i-blog.csdnimg.cn/blog_migrate/807e11758c4f9b6d9dc2730f3abb58c7.png




点击打开

假设背包的最大容量为10,有4件物品,每件物品的重量数组为:[5,4,6,3];相应的每件物品的价值数组为:[10,40,30,50]。


这个问题需要用到动态规划,所以我们首先需要知道这个问题的状态转移方程:假设我们用dp[i][j]表示前i件物品所占据容量j时所获得的最大价值,其中i表示物品的序号,j表示体积。由此,我们可以看出i的取值范围[1-4],j的取值范围为[1-10]。

状态转移方程:dp[i][j] = max{dp[i-1][j],dp[i-1][j-v[i]]+w[i]};其中v[]表示重量数组,w[]表示价值数组。

相应的中文描述为:我们在当前重量下放某一个物品时,有两种可能,放这个物品或者不放这个物品。所以当前dp[i][j]的取值为:若不放此物品,即为前i-1个物品所占据体积的最大价值。若确定放这个物品时,首先我们必须加上这个物品本身的价值,然后我们再计算当前剩余重量(当前重量-占据的重量)可否盛下前i-1个物品。若可以盛的下,就需要再加上前i-1个物品占据剩余的(j-v[i])体积时所获得的最大价值,用dp[i-1][j-v[i]]:

总的来说,这个是个前向取值的过程,他的每一部分解都是看其前面的值。

我们举例来看:

           

在初始时,假设书包的重量为0,则没有物品放置在书包内,所以第一列全为0,当没有任何物品放置在书包时,书包的重量为0,在任何重量中,其所获得的价值为0,所以第一行全为0。

 

 

0

1

2

3

4

5

6

7

8

9

10

0

0

0

0

0

0

0

0

0

0

0

0

Item1

0

 

 

 

 

 

 

 

 

 

 

Item2

0

 

 

 

 

 

 

 

 

 

 

Item3

0

 

 

 

 

 

 

 

 

 

 

Item4

0

 

 

 

 

 

 

 

 

 

 

 

现在,我们放入第一个物品,其重量为5,价值为10。第二行(Item1)表示放入第一个物品,在前4列中的重量<5,所以不能放,到第5列重量为5时,放入第一个物品,所获得的价值为10。在第6列,此时重量为6,还剩余1的重量,此时数据集中所有物品的重量均>1,没有办法再次放入另一个物品,7、8、9、10同理,所以在6、7、8、9、10列中,书包的价值都为10。

 

0

1

2

3

4

5

6

7

8

9

10

0

0

0

0

0

0

0

0

0

0

0

0

Item1

0

0

0

0

0

10

10

10

10

10

10

Item2

0

 

 

 

 

 

 

 

 

 

 

Item3

0

 

 

 

 

 

 

 

 

 

 

Item4

0

 

 

 

 

 

 

 

 

 

 

 

</pre><p></p><p>现在我们假设放入第二个物品,其重量为4,价值为40。第三行表示放入第二个物品,同理1、2、3列为0,在第4列,放入4,价值为40,在第5列,重量为5,不放入4,价值为10,放入4,价值基本上有40,剩余1,放不下前i件物品。所以此时第5列为40,第六列同理,第七列时,不放入4时的价值为10,放入4时,价值基本上有40,剩余3,不够所需的体积。第8列同理,第九列时,不放入4时价值为10,放入4时基本的价值为40,同时剩余5的重量,前1个物品所占5的最大价值为10,两者可以共存,价值为50,此时最大值为50。</p><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top"><p> </p></td><td valign="top"><p>0</p></td><td valign="top"><p>1</p></td><td valign="top"><p>2</p></td><td valign="top"><p>3</p></td><td valign="top"><p>4</p></td><td valign="top"><p>5</p></td><td valign="top"><p>6</p></td><td valign="top"><p>7</p></td><td valign="top"><p>8</p></td><td valign="top"><p>9</p></td><td valign="top"><p>10</p></td></tr><tr><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td></tr><tr><td valign="top"><p>Item1</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td></tr><tr><td valign="top"><p>Item2</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>50</p></td><td valign="top"><p>50</p></td></tr><tr><td valign="top"><p>Item3</p></td><td valign="top"><p>0</p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td></tr><tr><td valign="top"><p>Item4</p></td><td valign="top"><p>0</p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td></tr></tbody></table><p> </p><p>现在我们放入第三个物品,价值为6,中量为30。第四行表示放入第三个物品。在第四列,时,不放入第三个物品,最大价值为前i-1个物品占据4重量时的最大价值,第五列同理,在第六列时:</p><p>1.      当放入的重量< 第三个物品的重量时,不放入第三个物品,此时的最大价值为40</p><p>2.      当放入的重量 >= 放入第三个物品时,此时的基本价值为30,</p><p>2.1  查看能否与前面的物体共存,具体为,剩余0空间,最大价值我0,总和为30。</p><p>2.2  比较当前重量不放入第三个物品时的最大价值,求其最大值。最终取40.</p><p>第七列同理,第八列同理,第9列同理,第10列时:</p><p>1.      10>6,所以可以放入。此时的基本价值为30.</p><p>1.1   查看共存,剩余4,前2个物品占据4的最大价值为40,可以共存为70。</p><p>1.2   比较求最大值。当不放入第三个物品时的最大价值为50。最大值为70。</p><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top"><p> </p></td><td valign="top"><p>0</p></td><td valign="top"><p>1</p></td><td valign="top"><p>2</p></td><td valign="top"><p>3</p></td><td valign="top"><p>4</p></td><td valign="top"><p>5</p></td><td valign="top"><p>6</p></td><td valign="top"><p>7</p></td><td valign="top"><p>8</p></td><td valign="top"><p>9</p></td><td valign="top"><p>10</p></td></tr><tr><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td></tr><tr><td valign="top"><p>Item1</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td><td valign="top"><p>10</p></td></tr><tr><td valign="top"><p>Item2</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>50</p></td><td valign="top"><p>50</p></td></tr><tr><td valign="top"><p>Item3</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>0</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>40</p></td><td valign="top"><p>50</p></td><td valign="top"><p>70</p></td></tr><tr><td valign="top"><p>Item4</p></td><td valign="top"><p>0</p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td><td valign="top"><p> </p></td></tr></tbody></table><p>现在放入第4个物品,其重量为3,价值为50,第5行表示加入第四个物品。在1、2、3均小于第4个物品的重量3,不加入,在第4列:</p><p>1.      4>=4,加入4,此时的基本价值为50。</p><p>1.1   查看共存。加入了4时,4-4=0,无法共存。为50。</p><p>1.2   比较不加入。加入前40,加入后50,最大值为50。</p><p>第5列、第6列同理,第7列:</p><p>1.      7>4,可以加入4,此时的基本价值为50.</p><p>1.1   查看共存。剩余7-3=4,此重量的前3个物品、重量为4的价值为40,总共为90</p><p>1.2   比较。加入前40,最大值90.</p><p>第8列:</p><p>1.      8>3,可以加入,此时的基本价值为50</p><p>1.1   查看共存,剩余8-3=5,此重量的前3个物品、重量为5的价值为40,总共为90.</p><p>1.2   比较,加入前40,最大值为90.</p><p>同理第9列和第10列。</p><pre name="code" class="java" style="font-size: 14px; line-height: 21px;">package niuke;
import java.util.*;

public class BagQuestion {
	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);
		while(scan.hasNext()){
			int total = scan.nextInt();
			int number = scan.nextInt();
			int[] price = new int[number];
			int[] value = new int[number];
			for(int i=0;i<number;i++){
				price[i] = scan.nextInt();
				value[i] = scan.nextInt();
			}
			System.out.println(Arrays.toString(price));
			System.out.println(Arrays.toString(value));
			int[][] array = new int[number+1][total+1];
//			for(int i=0;i<total+1;i++){
//				array[0][i]=0;
//			}
//			for(int j=0;j<number+1;j++){
//				array[j][0]=0;
//			}
			for(int i=1;i<number+1;i++){
				for(int j=1;j<total+1;j++){
					if(price[i-1] <= j){
						array[i][j] = Math.max(array[i-1][j], array[i-1][j-price[i-1]]+value[i-1]);
					}else{
						array[i][j] = array[i-1][j];
					}
				}
			}
			System.out.println(array[number][total]);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值