• 完全背包问题


    题目来源:https://www.acwing.com/problem/content/3/


    基本思考框架

    C++代码

    #include<iostream>
    using namespace std;
    const int N = 1010;
    int f[N][N];
    int v[N],w[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++)
        {
            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<<f[n][m]<<endl;
    }
    

    优化思路
    我们列举一下更新次序的内部关系:

    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])
    

    有了上面的关系,那么其实k循环可以不要了,核心代码优化成这样:

    for(int i = 1 ; i <=n ;i++)
    for(int j = 0 ; j <=m ;j++)
    {
        f[i][j] = f[i-1][j];
        if((j-v[i]>=0)
            f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
    }
    

    这个代码和01背包的非优化写法很像啊!!!我们对比一下,下面是01背包的
    核心代码

    for(int i = 1 ; i <= n ; i++)
    for(int j = 0 ; j <= m ; j ++)
    {
        f[i][j] = f[i-1][j];
        if(j-v[i]>=0)
            f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
    }
    

    两个代码其实只有一句不同(注意下标)
    f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);//01背包
    f[i][j] = max(f[i][j],f[i][j-v[i]]+w[i]);//完全背包问题
    因为和01背包代码很相像,我们很容易想到进一步优化。核心代码可以改成下面这样

     for(int i = 1 ; i<=n ;i++)
        for(int j = v[i] ; j<=m ;j++)//注意了,这里的j是从小到大枚举,和01背包不一样
        {
                f[j] = max(f[j],f[j-v[i]]+w[i]);
        }
    

    综上所述,完全背包的最终写法如下:

    #include<iostream>
    using namespace std;
    const int N = 1010;
    int f[N];
    int v[N],w[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++)
        {
                f[j] = max(f[j],f[j-v[i]]+w[i]);
        }
        cout<<f[m]<<endl;
    }
    

    作者:在线白给
    链接:https://www.acwing.com/solution/content/5345/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    oracle——笔记——DDL语句
    Oracle中exp,imp的使用详解
    File类的简单使用
    理解Java的IO 流
    MyEclipse反编译Class文件的实现
    程序算法与人生选择
    Oracle 11g服务器与客户端卸载、安装
    Oracle字符集的查看查询和Oracle字符集的设置修改
    Java 对象的序列化 (Serializable)和反序列化
    Oracle创建表空间、创建用户以及授权、查看权限
  • 原文地址:https://www.cnblogs.com/hnkjdx-ssf/p/14002187.html
Copyright © 2020-2023  润新知