zoukankan      html  css  js  c++  java
  • 完全背包问题

    基本思考框架


    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(k*v[i]<=j)
    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/acwing/content/5345/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    linux配置ssh互信
    查看LINUX进程内存占用情况
    RSync实现文件备份同步详解
    rsync同步完整配置
    Linux下利用rsync实现多服务器文件同步
    Linux下的split 命令(将一个大文件根据行数平均分成若干个小文件)
    Linux大文件分割split和合并cat使用方法
    Linux计划任务入门详解
    一步一步理解最大熵模型
    一步一步理解word2Vec
  • 原文地址:https://www.cnblogs.com/WAsbry/p/12694909.html
Copyright © 2011-2022 走看看