AC代码:
#include <iostream>
#include<cstring>
#include <algorithm>
using namespace std;
const int N = 12010;
int v[N],w[N];
int f[2][N];
int cnt;
int main()
{
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++)
{
int a,b,s;cin>>a>>b>>s;
int k=1;
while ( k<=s )
{
cnt++;
v[cnt]=a*k;
w[cnt]=b*k;
s-=k;
k*=2;
}
if(s>0)
{
cnt++;
v[cnt]=a*s;
w[cnt]=b*s;
}
}
n=cnt;
int old=1,new1=0;
for(int i=1;i<=n;i++)
{
swap(new1,old);
for(int j=1;j<=m;j++)
{
f[new1][j]=f[old][j];
if(j>=v[i])
{
f[new1][j]=max(f[new1][j],f[old][j-v[i]]+w[i]);
}
}
}
cout<<f[new1][m];
return 0;
}
相关解释:
这里的话,我们直接按照01背包思路来写。但是这里我们不能把一个物品有多少份,而去给它分成多少份,这样的话,会mle。为什么呢?代码如下:
#include <iostream>
#include<cstring>
#include <algorithm>
using namespace std;
const int N = 2000010;
const int M = 2010;
int v[N],w[N];
int f[N][M];
int cnt=0;
int main()
{
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++)
{
int a,b,s;cin>>a>>b>>s;
int k=1;
while ( k<=s )
{
cnt++;
v[cnt]=a;
w[cnt]=b;
s-=k;
}
}
n=cnt;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
f[i][j]=f[i-1][j];
if(j>=v[i])
{
f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
}
}
cout<<f[n][m];
return 0;
}
这里我们的物品的数量是2000*1000,那么空间复杂度2000*1000*2000*4显然大于64000000。数组太大了,那么我们可以用滚动数组优化一下。
代码如下:
#include <iostream>
#include<cstring>
#include <algorithm>
using namespace std;
const int N = 2000010;
const int M = 2010;
int v[N],w[N];
int f[2][M];
int cnt=0;
int main()
{
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++)
{
int a,b,s;cin>>a>>b>>s;
int k=1;
while ( k<=s )
{
cnt++;
v[cnt]=a;
w[cnt]=b;
s-=k;
}
}
n=cnt;
int old=1,new1=0;
for(int i=1;i<=n;i++)
{
swap(old,new1);
for(int j=1;j<=m;j++)
{
f[new1][j]=f[old][j];
if(j>=v[i])
{
f[new1][j]=max(f[new1][j],f[old][j-v[i]]+w[i]);
}
}
}
cout<<f[new1][m];
return 0;
}
那么就算你用滚动数组优化了导致不会mle,那么此时也会tle。为什么呢,因为2000*1000*2000>1e8,所以就会tle。那么就要按照AC代码进行二进制优化,优化完就是2000*log(2000)*1000=2000*1000*11<1e8。显然时间符合了,再进行滚动数组优化,就可以AC了。最后的空间应该是12010*2*4<64000000。不进行滚动的话,12010*2000*4>64000000。会mle,所以每次做动态规划应该考虑时间和空间限制。