01背包

01背包

题目:

有容量为\(c\)的背包要装入体积为\(1,2,...n\)的物品,每种物品各一个,求恰好将背包装满的方案数。

分析:

我们用二维数组\(dp[i][j]\)表示物品按体积\(1,2,...n\)的顺序递增时,背包存储容量递增的方案数情况。\(i\)\(\left ( 0\leqslant i\leqslant n \right )\)表示有体积为\(0,1,...i\)的物品各一个,\(j\)表示背包的容量为\(j\)
首先,当已有的物品体积数量为0,也就是相当于只有一个体积为0的物品时,背包容量\(j\)为0的方案数只有1个。

当已有的物品体积数量\(i\)为0,背包容量\(j\)大于0的方案数全部为0。

当已有的物品体积数量\(i\)大于0,背包容量\(j\)为0的方案数按照\(dp\left [ i \right ]\left [ j \right ]= dp\left [ i-1 \right ]\left [ j \right ]\quad(i>j)\)全部为1。
也就是:
\begin{aligned}
dp\left [ 0 \right ]\left [ 0 \right ]=dp\left [ i>0 \right ]\left [ 0 \right ]= 1
\end{aligned}

\begin{aligned}
dp\left [ 0 \right ]\left [ j>0 \right ]= 0
\end{aligned}

状态转移方程:
\begin{aligned}
dp\left [ i \right ]\left [ j \right ]= dp\left [ i-1 \right ]\left [ j \right ]\quad(i>j)
\end{aligned}

\begin{aligned}
dp\left [ i \right ]\left [ j \right ]= dp\left [ i-1 \right ]\left [ j \right ]+dp\left [ i-1 \right ]\left [ j-i \right ]\quad(i\leqslant j)
\end{aligned}
二维数组是从上到下、从左到右进行计算,每个元素都与之前已经计算过元素相关。

对于第\(i\)\(j\)列的元素:

如果\(i>j\),也就是新添加的可选物品的体积大于背包的容积,无法放入背包,所以新添加的可选物品不能够增加方案数。

如果\(i<=j\),新添加的可选物品的体积小于背包的容积,有可能与其他物品组合装入背包,这时方案数为当没有添加入\(i\)体积物品时背包容量为j的方案数\(dp[i-1][j]\)和当没有添加入\(i\)体积物品时但背包容量恰好可以装入i体积物品的方案数 \(dp[i-1][j-i]\)。这样逐行计算即可知道所有情况下的方案数。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int dp[maxn][maxn];
int w[maxn],v[maxn];
int c,n;

int main(){
	cin>>c>>n;
	for (int i=1;i<=n;i++)
		cin>>w[i]>>v[i];
	for (int i=1;i<=n;i++)//循环n个物品 
		for (int j=1;j<=c;j++){
			if (w[i]<=j)//如果第i个物品的容量小于背包容量j,说明可以放进背包。 
			   dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
  //不放入背包 背包内物品最大价值仍为dp[i-1][j] 故dp[i][j]=dp[i-1][j];
////放入背包 第i件物品容量表示为w[i],该物品的价值表示为v[i],那么背包剩余容量为j-w[i].故dp[i][j]=dp[i-1][j-w[i]]+v[i]
////(已放入第i件物品 它的价值为v[i] 剩余容量能达到的最大价值为dp[i-1][j-w[i]]
		    else
			   dp[i][j]=dp[i-1][j];//不能放入背包 背包内物品最大价值仍为dp[i-1][j] 故dp[i][j]=dp[i-1][j]
			   
		cout<<i<<' '<<j<<' '<<dp[i][j]<<endl; 
	}
	cout<<dp[n][c];
} 

题目:

\(n\)件物品,每件物品的重量为\(w[i]\),价值为\(v[i]\)。现有一个容量为\(c\)的背包,问如何选取物品放入背包,使得背包内物品的总价值最大。其中每种物品都只有一件。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100;
int dp[maxn][maxn];
int w[maxn],v[maxn];
int c,n;

int main(){
	cin>>c>>n;
	for (int i=1;i<=n;i++)
		cin>>w[i]>>v[i];
	for (int i=1;i<=n;i++)//循环n个物品 
		for (int j=1;j<=c;j++){
			if (w[i]<=j)//如果第i个物品的容量小于背包容量j,说明可以放进背包。 
			   dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
  //不放入背包 背包内物品最大价值仍为dp[i-1][j] 故dp[i][j]=dp[i-1][j];
////放入背包 第i件物品容量表示为w[i],该物品的价值表示为v[i],那么背包剩余容量为j-w[i].故dp[i][j]=dp[i-1][j-w[i]]+v[i]
////(已放入第i件物品 它的价值为v[i] 剩余容量能达到的最大价值为dp[i-1][j-w[i]]
		    else
			   dp[i][j]=dp[i-1][j];//不能放入背包 背包内物品最大价值仍为dp[i-1][j] 故dp[i][j]=dp[i-1][j]
			   
		cout<<i<<' '<<j<<' '<<dp[i][j]<<endl; 
	}
	cout<<dp[n][c];
} 
posted @ 2020-10-07 22:45  Treasure_lee  阅读(115)  评论(0)    收藏  举报