遇到这种问题,如果理解了01背包的话,其实很简单,只要把每次取的情况分清楚就好了:
1:不取 直接等于上一个就好了f[i][j]=f[i-1][j];
2:取 其实想清楚也很简单 有i个物品重量为j-v[i]的最优解时加上这个物品的价值f[i][j]=f[i][j-v[i]+w[i]
当然是j>=v[i]的时候
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=1890;
int v[N],w[N],n,m,f[N][N];
int main(){
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=1;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;
const int N=1890;
int v[N],w[N],n,m,f[N];
int main(){
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]);//注意公式的变化i是i不是i-1
}
}
cout<<f[m];
return 0;
}
f[j]=max(f[j],f[j-v[i]]+w[i]);在这个地方的f[j]的转换是没有变化的,跟01背包的区别比较大。01背包是需要用到i-1的情况,这样的话有冲突,这里只要用到自己本行的情况。