背包问题
01背包
每件物品最多只使用一次。
for(int i=1; i<=n; i ++ ){
int v, w;
cin>>v>>w;
for(int j=m; j>=v; j--){
dp[j] = max(dp[j],dp[j-v]+w);
}
}
完全背包
每件物品可以使用无限次。
for(int i=1; i<=n; i++){
int v, w;
cin>>v>>w;
for(int j=0; j<=m; j++){
if(j>=v)dp[j] = max(dp[j],dp[j-v]+w);
}
}
多重背包
每件物品最多使用 s [ i ] s[i] s[i] 次。
朴素写法
for(int i = 1; i <= n; i ++ ){
int v, w, s;
cin>>v>>w>>s;
for(int j=m; j >= 1; j--){
for(int k = 1; k <= s; k ++ ){
if(k*v<=j)dp[j] = max(dp[j],dp[j-k*v]+k*w);
}
}
}
n m l o g s nmlogs nmlogs二进制优化,利用倍增的思想
cin>>n>>m;
for(int i = 1; i <= n; i ++ ){
int a, b, c;
cin>>a>>b>>c;
int k = 1;
while(k<=c){
v[cnt] = k*a;
w[cnt] = k*b;
cnt++;
c -= k;
k <<= 1;
}
if(c > 0){
v[cnt] = c*a;
w[cnt] = c*b;
cnt++;
}
}
for(int i = 0; i < cnt; i ++ ){
for(int j=m; j>=v[i]; j--){
dp[j] = max(dp[j], dp[j-v[i]]+w[i]);
}
}
cout<<dp[m]<<endl;
分组背包
每组中最多只可以选择一个物品。
cin>>n>>m;
for(int i = 0; i < n; i ++ ){
cin>>s[i];
for(int j = 0; j < s[i]; j ++ ){
cin>>v[i][j]>>w[i][j];
}
}
for(int i = 0; i < n; i ++ ){
for(int j = m; j >= 0; j -- ){
for(int k = 0; k < s[i]; k++){
if(j>=v[i][k])dp[j] = max(dp[j], dp[j-v[i][k]] + w[i][k]);
}
}
}