动态规划_01背包问题

文章介绍了如何使用动态规划解决01背包问题,通过比较物品价值与剩余背包容量,计算在给定背包容量下可以获得的最大物品总价值。
摘要由CSDN通过智能技术生成

描述

一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是 W1,W2,...,Wn,它们的价值分别为 C1,C2,...,Cn,求旅行者能获得最大总价值。

输入描述

1 行:两个整数,M (背包容量,M200 )和 N ( 物品数量,N30 )
2…N+1 行:每行二个整数 Wi,Ci,表示每个物品的重量和价值。

输出描述

仅一行,一个数,表示最大总价值。

样例输入

10 4
2 1
3 3
4 5
7 9

样例输出

12

数据范围与提示

M≤200N≤30

问题分析

物品编号为i,,背包容量为j ,背包价值为p[i][j]

1)第一行(i=1)尝试将序号为1的物品放入背包:

背包容量为1时,什么都装不进去背包价值为0P[1][1]=0

背包容量为2时,正好1号物品重量为2,背包价值为1P[1][2]=1

因为是01背包问题,物品只有一个,所以第一行后面的背包价值都为1

序号i

背包容量

1

2

3

4

5

6

7

8

9

10

重量

价值

1

2

1

0

1

1

1

1

1

1

1

1

1

2

3

3

3

4

5

4

7

9

2)第二行(i=2)尝试将序号为12的物品放入背包:

背包容量为1时,什么都装不进去背包价值为0P[2][1]=0

背包容量为2时,正好1号物品重量为2,背包价值为1P[2][2]=1

背包容量为3时,对比第一行是背包价值为1,即 P[1][2]=1。现新增加了第2种物品,新增加的重量为3,正好为背包容量。因此 P[2][3]=3

背包容量为4时,也只能放重量为3的物品P[2][4]=3

背包容量为5时,对比第一行是背包价值为1,即 P[1][5]=1。现新增加了第2种物品,背包装上第2种物品后剩余容量为2,正好装第1种物品,因此 P[2][5]=4P[i][j]=max(P[i-1][j]+i种物品价值,P[i-1][j])。

序号

i

背包容量

1

2

3

4

5

6

7

8

9

10

重量

价值

1

2

1

0

1

1

1

1

1

1

1

1

1

2

3

3

0

1

3

3

4

4

4

4

4

4

3

4

5

4

7

9

2)第三行(i=3)尝试将序号为124的物品放入背包:

背包容量为1时,什么都装不进去背包价值为0P[3][1]=0

背包容量为2时,正好1号物品重量为2,背包价值为1P[3][2]=1

背包容量为3时,对比第一行是背包价值为1,即 P[2][3]=3。现新增加了第2种物品,新增加的重量为3,不够背包容量。因此 P[3][3]=3

背包容量为4时,对比第二行是背包价值为3,即 P[2][4]=3。现新增加了第3种物品,背包装上第3种物品后剩余容量为0,因此 P[3][4]=5

背包容量为5时,对比第二行是背包价值为4,即 P[2][5]=4。现新增加了第3种物品,背包装上第3种物品后剩余容量为1,装不上其它物品,因此 P[3][5]=5。

背包容量为6时,对比第二行是背包价值为4,即 P[2][6]=4。现新增加了第3种物品,背包装上第3种物品后剩余容量为2,正好撞上1号产品价值为1,因此 P[3][6]=6。

…………………..

依次类推完成表格:

序号

i

背包容量

1

2

3

4

5

6

7

8

9

10

重量

价值

1

2

1

0

1

1

1

1

1

1

1

1

1

2

3

3

0

1

3

3

4

4

4

4

4

4

3

4

5

0

1

3

5

5

6

8

8

9

9

4

7

9

0

1

3

5

5

6

9

9

10

12

推理:

背包容量为j时,可装入背包的最大价值为:

如果j<i 物品重量:直接取上方表格背包价值,即p[i][j]= p[i-1][j];

如果j>=i 物品重量:

P[i][j]=max(i种物品价值+去掉第i种物品重量后的背包最大价值,P[i-1][j]) = max(i种物品价值+ P[i-1][j-i物品价值]P[i-1][j])

实现代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
	int p[201][201] = {},b[201][2] = {} ;//p[201][201]背包价值 b[201][2] 物品重量价值
    int  M,N; //M 背包容量,N物品数量
	cin >> M >> N;
	for(int i = 1;i <= N;i++)
	{
		cin >> b[i][0] >> b[i][1];
	}
	for(int i = 1;i <=N;i++)
	{
		for(int j = 1;j <= M;j++)
	    {
            if (j < b[i][0]) 
            {
                 p[i][j]=p[i-1][j];
            }
            else
            {
                 int val= j-b[i][0];//去掉第i个物品重量以后背包剩余重量 
                 p[i][j]=max( b[i][1] + p[i-1][val] , p[i-1][j]) ;
            }
               
	    }
	}
    cout << p[N][M];
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值