【动态规化】完全背包

在这里插入图片描述
同样先给出需要记住的一维代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int v[MAXN]; // 体积 
int w[MAXN]; // 价值 
int dp[MAXN];

int main() 
{
    int n, m;//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++){
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }           
	cout << dp[m];
    return 0;
}

与一维的01背包代码仅仅只有j循环的顺序不同。
为什么?
同样我们要仿照二维的思路思考
如果是二维的话推理可得

dp [ i ][ j ] = max( dp[ i - 1][ j ] , dp[ i - 1][ j - v ] + w , dp[ i -1][ j - 2v ] + 2w , dp [ i-1 ][ j - 3v] + 3w , …)

这么多项啊,那岂不是要循环,又多加一维,三维循环?
可是 我们可以思考一下,f[i][j-v]等于多少?
实际上,在完全背包问题里,

dp[ i ][ j - v ] = max(dp[ i - 1 ][ j - v ],dp[ i - 1 ][ j - 2v ]+w,dp[ i -1 ][ j - 3v ]+2w,…)

观察一下两个式子,我们将它们结合一下
dp [ i ][ j ]=max(dp[ i - 1 ][ j ],dp[ i ][ j - v ]+w);

所以完全背包的一维的程序里面的 j 循环是顺序的,
这样 dp [ j - v[ i ]] 就先被更新,就相当于dp[ i ][ j - v[ i ] ]

这里也放上二维的代码供参考

#include <iostream>
using namespace std;
int w[1005],v[1005],dp[1005][1005];
int n,m;
int main(){
    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++){
            if(v[i]>j) dp[i][j]=dp[i-1][j];
            else dp[i][j] = max(dp[i-1][j], dp[i][j-v[i]]+w[i]);
        }
    }
    cout<<dp[n][m];
}

如果是求物品总体积恰等于背包容量,
要对dp[ i ] 数组初始化
for(int i = 1; i <= m ; i ++) dp [ i ] = - inf ;(求最大值)
for(int i = 1; i <= m ; i ++) dp [ i ] = inf ;(求最小值)
只让 dp [ 0 ] = 0;

发布了62 篇原创文章 · 获赞 0 · 访问量 657

猜你喜欢

转载自blog.csdn.net/weixin_44745441/article/details/104971782
今日推荐