背包详谈

背包详谈

问题:在n种物品中选取若干件放在空间为m的背包里,每种物品的体积为w1,w2,…,wn,与之相对应的价值为v1,v2,…,vn.求解怎么装物品可使背包里物品总价值最大

  • 01背包——每种物品只有两种性质:选或不选
  • 完全背包——每种物品有无限个

—————————————我是分割线—————————————————
dp[i][j]表示前i个物品达到的重量j所达到的最高价值
则dp[n][m]为所求的答案

  1. 01背包: 我们已经知道对于第i个物品,只有两个性质,选或不选;如果选的话那么dp[i][j]dp[i - 1][j - w[i]] + v[i],如果不选的话那么就是dp[i][j]=dp[i-1][j];然后因为背包总价值最大,所以要从二者中取MAX;
  2. 完全背包:按最暴力的方法就是将完全背包看成无限个01背包,则dp[i][j] = max(dp[i - 1][j],dp[i][j - w[i]]);(论述已省)

二维变一维

  • 01背包:我们很容易发现dp[i]只会被i以前的状态影响,那么我们为何不逆序枚举,让dp[i]不被i之前的状态影响呢.
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100 + 10;
int w[maxn],v[maxn];
int dp[maxn];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++)scanf("%d%d",&w[i],&v[i]);
	for(int i = 1; i <= n; i++)
		for(int j = m; j >= w[i]; j--)
			dp[j] = max(dp[j],dp[j - w[i]] + v[i]);
	return 0;
}
//应该很好理解
//吧?
  • 完全背包:原理与01背包差不太多.只要顺序枚举即可
for(int i = 1; i <= n; i++)
	for(int j = w[i]; j <= m; j++)
		dp[j] = max(dp[j],dp[j - w[i]] + v[i]);

滚动数组

从前面我们就可以发现,dp[i][j]只与这一状态与上一状态有关.之前存的数据就没有用了,可以将它舍弃,所以我们可以用2M的空间存储数据,循环滚动使用,2 * m可以达到n * m同样的效果,这无疑优化了很大的空间.

//————完全
int now = 1;
for(int i = 1; i <= n; i++)
{
	for(int j = w[i]; j <= m; j++)
		dp[now][j] = max(dp[1 - now][j],dp[now][j - w[i]] + v[i]);
	now = 1 - now;
}
//————01
int now = 1;
for(int i = 1; i <= n; i++)
{
	for(int j = w[i]; j <= m; j++)
		dp[now][j] = max(dp[1 - now][j],dp[1 - now][j - w[i]] + v[i]);
	now = 1 - now;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值