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背包问题的及其优化的主要内容,如果未能解决你的问题,请参考以下文章