day51:完全背包(动态规划)

问题描述:
有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。第 i 种物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。数据范围:0

  • 输入样例
    4 5
    1 2
    2 4
    3 4
    4 5
  • 输出样例:
    10

与01背包问题类似,不同之处在于完全背包问题可无限放入。完全背包公式推导如下,

f[i , j ] = max( f[i-1,j] , f[i-1,j-v]+w ,  f[i-1,j-2*v]+2*w , f[i-1,j-3*v]+3*w , .....)f[i , j-v]= max(            f[i-1,j-v]   ,  f[i-1,j-2*v] + w , f[i-1,j-2*v]+2*w , .....)由上两式,可得出如下递推关系:f[i][j]=max(f[i,j-v]+w , f[i-1][j])
图片参考链接

#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];

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=1;j<=m;j++)
        {
            f[i][j]=f[i-1][j];
            if(j>=v[i]) f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
        }
    }
    cout<<f[n][m]<<endl;
    return 0;
}

优化后的代码
f[ i ][ j ]=f[ i-1 ][ j ];等价于f[ j ]=f[ j ],由于计算先后顺序,左边的数字优先于右边的数字计算,f[ j ] = max(f[ j ],f[ j-v[i] ]+w[ i ]); 等价于 f[ i ][ j ]=max(f[ i ][ j ],f[ i] [ j-v[i] ]+w[ i ]);原因类似,注意与01背包问题优化的时候循环方式不变依旧是从小到大,但是01背包问题f[ i ][ j ]=max(f[ i ][ j ],f[ i-1 ][ j-v[i] ]+w[ i ]); 与f [ j ]=max(f[ j ],f[ j-v[i] ]+w[ i ]); 是不等价的,因为需要计算的是f[ i-1 ][ j-v[i] ]而不是f[ i][j-v[i] ] ,所以如果设置成从大到小就能保证使用到的f[ j-v[ i ]]先于f[ j ] 被计算出来,也就是使用的是上一层的f[ j-v[i] ]。

#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N];

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=v[i];j<=m;j++)
        {
            f[j]=max(f[j],f[j-v[i]]+w[i]);
        }
    }
    cout<<f[m]<<endl;
    return 0;
}

你可能感兴趣的:(背包九讲)