dp(01背包,完全背包)

dp(01背包,完全背包),第1张

dp(01背包,完全背包) 一:01背包

01背包问题的情景:一个有固定重量的背包,容量为V。一共有n件商品,每件商品的价值为vi,让你挑选商品(每件物品只有一个),你挑选的商品重量不能超过背包的容量(小于等于),并且使得你挑选的物品价值最大(尽可能的使得价值最大)。

01背包问题的分析总的来说,其实就是状态方程的推导一般为f(i,j);

我们把背包看成是一个集合,01背包问题就是集合分成两部分,一个是不包含第i件商品,另一个是包含第i件商品;

方程分别就是f(i-1,j)和f(i-1,j-v[i])+w[i];

因此代码如下(二维):

#include
using namespace std;
int v[1005];
int w[1005];
int f[1005][1005];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            f[i][j]=f[i-1][j];
            if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
        }
    cout< 

但是二维我们最好可以优化成为一维数组

#include
using namespace std;
int v[1005];
int w[1005];
int f[1005];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)  cin>>v[i]>>w[i];
	for(int i=1;i<=n;i++)
	 	for(int j=m;j>=v[i];j--)
	 	{
	 		f[j]=max(f[j],f[j-v[i]]+w[i]);
		 }
    cout< 
2.完全背包 

完全背包的情景和01背包的情景相似,但是商品是无限拿的,不是只有一件。

分析状态方程的时候,我们可以根据01方程的思想,想象一个集合,一部分是第i件物品没有拿,一个是第i件物品拿了,拿了多少件的我们定义为k件。

因此两部分的方程为f(i-1,j)  f(i,j-k*v[i])+k*w[i])

所以代码如下(二维):

#include
using namespace std;
int v[1005];
int w[1005];
int f[1005][1005];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)  cin>>v[i]>>w[i];
	
	for(int i=1;i<=n;i++)
	 	for(int j=0;j<=m;j++)
	 	   for(int k=0;k*v[i]<=j;k++)
	 	   {
               f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
		   }
    cout< 

这种情况一般都超时,因此要优化

#include
using namespace std;
int v[1005];
int w[1005];
int f[1005];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)  cin>>v[i]>>w[i];
	for(int i=1;i<=n;i++)
	 	for(int j=v[i];j<=m;j++)
	 	{
	 		f[j]=max(f[j],f[j-v[i]]+w[i]);
		 }
    cout< 

可以发现,其实01背包和完全背包就是二层循环不一样。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5713760.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存