目录
01背包:
01背包转移方程:
01背包注意事项:
-
循环是0~m。
-
下标要注意。
- 每次循环开始时,f[i][j] = f[i][j-1]。
- f[i][j] = f[i][j-1]后要加判断:if(j>=v[i])否则会访问负下标。
- 结合代码会好看一些。
01背包代码:
#include<bits/stdc++.h>
using namespace std;
int a[1010];
int v[1010],w[1010];
int f[1010][1010];
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++)
{
f[i][j] = f[i-1][j];
if(j<v[i])
{
continue;
}
f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
}
cout<<f[n][m];
return 0;
}
01背包空间优化版(滚动数组):
#include<bits/stdc++.h>
using namespace std;
int a[1010];
int v[1010],w[1010];
int f[1010];
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=m;j>=v[i];j--)
{
f[j] = max(f[j],f[j-v[i]]+w[i]);
}
}
cout<<f[m];
return 0;
}
时间复杂度:
完全背包:
完全背包转移方程:
完全背包变量意思:
i:下标
j:容量
k:每个物品个数
完全背包朴素版:
#include<bits/stdc++.h>
using namespace std;
int a[1010];
int v[1010],w[1010];
int f[1010][1010];
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-v[i]*k]+w[i]*k);
}
}
}
cout<<f[n][m];
return 0;
}
复杂度:
完全背包时间优化版:
#include<bits/stdc++.h>
using namespace std;
int a[1010];
int v[1010],w[1010];
int f[1010][1010];
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++)
{
f[i][j] = f[i-1][j];
if(j>=v[i]) f[i][j] = max(f[i][j],f[i][j-v[i]]+w[i]);
}
}
cout<<f[n][m];
return 0;
}
复杂度:
完全背包时间+空间优化版(滚动数组):
#include<bits/stdc++.h>
using namespace std;
int a[1010];
int v[1010],w[1010];
int f[1010];
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];
return 0;
}
复杂度:
多重背包:
多重背包转移方程:
多重背包朴素写法(暴力):
#include<bits/stdc++.h>
using namespace std;
int a[1010];
int v[1010],w[1010];
int f[1010][1010];
int s[1010];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>v[i]>>w[i]>>s[i];
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int k=0;k*v[i]<=j&&k<=s[i];k++)
{
f[i][j] = max(f[i][j],f[i-1][j-v[i]*k]+w[i]*k);
}
}
}
cout<<f[n][m];
return 0;
}
复杂度:
多重背包时间+空间优化版:(二进制分组优化)
#include<bits/stdc++.h>
using namespace std;
int f[25000];
int v[25000];
int w[25000];
int cnt;
void change(int a,int b,int s)
{
int k=1;
while(k<=s)
{
cnt++;
v[cnt] = a*k;
w[cnt] = b*k;
s-=k;
k*=2;
}
if(s)
{
cnt++;
v[cnt] = a*s;
w[cnt] = b*s;
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int a,b,s;
cin>>a>>b>>s;
change(a,b,s);
}
for(int i=1;i<=cnt;i++)
{
for(int j=m;j>=v[i];j--)
{
f[j] = max(f[j],f[j-v[i]]+w[i]);
}
}
cout<<f[m];
return 0;
}
复杂度:
分组背包:
分组背包转移方程:
分组背包空间优化版:(滚动数组)
#include<bits/stdc++.h>
using namespace std;
int v[110][110],w[110][110];
int s[110];
int f[110];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>s[i];
for(int j=1;j<=s[i];j++)
{
cin>>v[i][j]>>w[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=m;j>=0;j--)
{
for(int k=0;k<=s[i];k++)
{
if(v[i][k]<=j)
{
f[j] = max(f[j],f[j-v[i][k]]+w[i][k]);
}
}
}
}
cout<<f[m];
return 0;
}