01背包问题的及其优化

Posted aininot260

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了01背包问题的及其优化相关的知识,希望对你有一定的参考价值。

有N件物品和一个容量为C的背包,第i件物品的费用是c[i],价值是w[i],求将若干件物品放入背包所能够获得的最大价值。

每种物品只有一件,可以选择放或者是不放

使用f(i,v)表示前i件物品恰好放入一个容量为v的背包所能获得的最大价值

状态转移方程:

f(i,v)=max{f(i-1,v),f(i-1,v-c[i])+w[i]}

时间复杂度为O(N*V),空间复杂度可以优化为O(V),即采用滚动数组的形式,与完全背包的实现相比较,这里是逆推,完全背包是正推

 f(v)=max{f(v),f(v-c[i])+w[i]}

首先我们给出第一个状态转移方程的实现:

int f[maxn][maxv];
int ans=0;
void dp()
{
    for(int i=1;i<=N;i++)
    for(int j=1;j<=V;j++)
    {
        if(v[i]<=j)
            f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
        else
            f[i][j]=f[i-1][j];
    }
    ans=f[N][V];
}

可以看到循环变量是很好写的

接下来我们给出滚动数组形式转移方程的实现:

int f2[maxv];
void dp2()
{
    for(int i=1;i<=N;i++)
    for(int j=V;j>=0;j--)
    {
        if(v[i]<=j)
            f2[j]=max(f2[j],f2[j-v[i]]+w[i]);
    }   
    ans=f2[V];
} 

这种方法虽然省空间,但是中间结果都被覆盖掉了

最后我们给出一个完整的代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=1005;
 5 const int maxv=1005;
 6 int N,V;
 7 int v[maxn],w[maxn];
 8 int f[maxn][maxv];
 9 int ans=0;
10 void dp()
11 {
12     for(int i=1;i<=N;i++)
13     for(int j=1;j<=V;j++)
14     {
15         if(v[i]<=j)
16             f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
17         else
18             f[i][j]=f[i-1][j];
19     }
20     ans=f[N][V];
21 }
22 int f2[maxv];
23 void dp2()
24 {
25     for(int i=1;i<=N;i++)
26     for(int j=V;j>=0;j--)
27     {
28         if(v[i]<=j)
29             f2[j]=max(f2[j],f2[j-v[i]]+w[i]);
30     }   
31     ans=f2[V];
32 } 
33 int main()
34 {
35     cin>>V>>N;
36     for(int i=1;i<=N;i++)
37         cin>>v[i]>>w[i];
38     dp2();
39     cout<<ans;
40     return 0;
41 }
42  

 

以上是关于01背包问题的及其优化的主要内容,如果未能解决你的问题,请参考以下文章

动态规划问题3--多重背包

HDU #2191 买米问题 多重背包及其优化

01背包的优化问题

动态规划背包问题总结:01完全多重与其二进制优化分组背包 题解与模板

01背包问题模板代码

01背包思想和优化