动态规划(完全背包问题)优化版

前情提要动态规划(完全背包问题)-CSDN博客https://mp.csdn.net/mp_blog/creation/editor/123909609

你已经学会了完全背包问题的写法,那么让我们看看是否能优化这个代码吧;

通过观察我们代码,比起01问题,我们新加入的代码有一个比较过程,那么基于此,我们来找规律吧;

g[i][j]=max(g[i][j],g[i][j-v[i]]+w[i],g[i][j-2*v[i]]+2*w[i]...)
g[i][j-v[i]]=max(   g[i][j-v[i]],     g[i][j-2*v[i]]+w[i]  ...)
g[i][j-2*v[i]]=max(                   g[i][j-2*v[i]]       ...)

我们在找max的时候,在条件(j>=v[i])成立的时候,是从多个值中找一个最大的,这时我们发现:当j>=2*v[i]时成立,每一个式子除了第一项,他的其余值成为一个集合时,等于他的下一个式子内,可以取最大值的集合+w[i];

这个时候我们就有了一个等价关系:

g[i][j]=max(g[i][j],g[i][j-v[i]]+w[i]);

这段代码是一定成立的,因为g[i][j-v[i]]一定是在g[i][j]之前被计算出来的,所以我们可以直接拿来比较,于是我们的代码就得到了如下简化:

#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N=1010;
int v[N],w[N];
int g[N][N];

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++) 
		{
			g[i][j]=g[i-1][j];//正常继承,如果不正常继承,可能会导致在j<v[i]时 
			                  //这时下面不等式成立,于是这里没有变化还是0,
							  //但其实可能会有其他优解而导致答案错误 
			if(j>=v[i])
			g[i][j]=max(g[i][j],g[i][j-v[i]]+w[i]);
		}
	
	cout<<g[n][m];
 } 

至此...没有结束!!!

我们发现,这里的代码和01背包问题很相似,不妨大胆一点我们来直接优化乘一维,方法与之前的一样。首先,我们需要去掉一维,然后对下面进行改动,如果改变合理就保留,否则就修改;

那么我们可以得到如下代码:

#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N=1010;
int v[N],w[N];
int g[N];

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++)
			g[j]=max(g[j],g[j-v[i]]+w[i]);
          //g[i][j]=max(g[i][j],g[i][j-v[i]]+w[i]);
	cout<<g[m];
 } 

这个时候小伙伴问了,诶呀,你刚才改的时候都把j的遍历顺序改变了,这次怎么不改呢?

原因是,我们发现,01背包问题考虑的是是否带第i个物品,这就导致了我们需要取第i-1行的数据来计算最优解,但是这里我们没有用到底i-1行,这也是我们可以直接删除一维的原因。

至此,完结撒花;’

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值