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

    完全背包

    有n种重量和价值分别为wi,vi的物品,从这些物品中挑选总重量不超过W的物品,求出挑选物品价值总和的最大值。在这里,每种物品可以挑选任意多件。

    限制条件:1<=n<=100,1<=wi,vi<=100,1<=W<=10000。 

    分析一下:dp[i+1][j]代表从前i种物品中挑选总重量不超过j时总价值的最大值。

    递推关系为:dp[0][j]=0;

          dp[i+1][j]=max{dp[i][j-k*w[i]]+k*v[i] | 0<=k}

    可以写出程序如下

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<memory.h>
     4 using namespace std;
     5 const int max_n=101;
     6 int w[max_n+1];
     7 int v[max_n+1];
     8 int n,r,W;
     9 int main()
    10 {
    11     cin>>n;
    12     for(int i=0;i<n;i++)
    13     {
    14         cin>>w[i]>>v[i];
    15     }
    16     cin>>W;
    17     int dp[n+1][W+1];
    18     memset(dp,0,sizeof(dp));
    19     for(int i=0;i<n;i++)
    20     {
    21         for(int j=0;j<=W;j++)
    22         {
    23             for(int k=0;k*w[i]<=j;k++)
    24             {
    25                 dp[i+1][j]=max(dp[i+1][j],dp[i][j-k*w[i]]+k*v[i]);
    26             }
    27         }
    28     }
    29     cout<<dp[n][W]<<endl;
    30     return 0;
    31 }
    View Code

    关于k的循环最坏可能从0循环到W,所以这个算法的复杂度为O(nW*W)

    可以做变形:max{dp[i][j-k*w[i]]+k*v[i] | 0<=k}

         =max(dp[i][j],max{dp[i][j-k*w[i]]+k*v[i] | 1<=k})

           =max(dp[i][j],max{dp[i][(j-w[i])-k*w[i]]+k*v[i] | 0<=k}+v[i])

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

    所以递推关系式

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

    我们和01背包的递推关系式比较一下

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

    复杂度降为O(nW)

    程序如下

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<memory.h>
     4 using namespace std;
     5 const int max_n=101;
     6 int w[max_n+1];
     7 int v[max_n+1];
     8 int n,r,W;
     9 int main()
    10 {
    11     cin>>n;
    12     for(int i=0;i<n;i++)
    13     {
    14         cin>>w[i]>>v[i];
    15     }
    16     cin>>W;
    17     int dp[n+1][W+1];
    18     memset(dp,0,sizeof(dp));
    19     for(int i=0;i<n;i++)
    20     {
    21         for(int j=0;j<=W;j++)
    22         {
    23             if(j>=w[i])
    24             {
    25                 dp[i+1][j]=max(dp[i][j],dp[i+1][j-w[i]]+v[i]);
    26             }
    27             else
    28             {
    29                 dp[i+1][j]=dp[i][j];
    30             }
    31         }
    32     }
    33     cout<<dp[n][W]<<endl;
    34     return 0;
    35 }
    View Code

    也可以通过过重复利用一个数组来实现dp。这个比较不好理解一些。

    看01背包的情况

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<memory.h>
     4 using namespace std;
     5 const int max_n=101;
     6 int w[max_n+1];
     7 int v[max_n+1];
     8 int n,r,W;
     9 int main()
    10 {
    11     cin>>n;
    12     for(int i=0;i<n;i++)
    13     {
    14         cin>>w[i]>>v[i];
    15     }
    16     cin>>W;
    17     int dp[W+1];
    18     memset(dp,0,sizeof(dp));
    19     for(int i=0;i<n;i++)
    20     {
    21         for(int j=W;j>=w[i];j--)
    22         {
    23             dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    24         }
    25     }
    26     cout<<dp[W]<<endl;
    27     return 0;
    28 }
    View Code

    看完全背包的情况

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<memory.h>
     4 using namespace std;
     5 const int max_n=101;
     6 int w[max_n+1];
     7 int v[max_n+1];
     8 int n,r,W;
     9 int main()
    10 {
    11     cin>>n;
    12     for(int i=0;i<n;i++)
    13     {
    14         cin>>w[i]>>v[i];
    15     }
    16     cin>>W;
    17     int dp[W+1];
    18     memset(dp,0,sizeof(dp));
    19     for(int i=0;i<n;i++)
    20     {
    21         for(int j=w[i];j<=W;j++)
    22         {
    23             dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    24         }
    25     }
    26     cout<<dp[W]<<endl;
    27     return 0;
    28 }
    View Code

    两者的差异只有循环的方向

  • 相关阅读:
    前端优化分析 之 javascript放在底部
    HTML、SHTML、XHTML、DHTML、XML有什么不同
    web项目开发流程及规范
    sql developer连接mysql数据库
    hibernate自动创建表报错,提示不存在
    04关键字和标识符
    03注释与API文档
    WEB应用中的路径问题及乱码问题
    01java开发环境配置
    Eclipse Java EE IDE for Web Developers 4.5.1 安装hibername tools 插件
  • 原文地址:https://www.cnblogs.com/wangkaipeng/p/6429513.html
Copyright © 2011-2022 走看看