1.01背包
N个物品,背包体积为V,每件物品最多只用一次。
每个问题两个属性:
1.朴素写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m;
int v[N],w[N]; //v[N]物品的体积,w[N]物品的价值
int 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 = 0;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] << endl;
return 0;
}
2.优化写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m;
int v[N],w[N]; //v[N]物品的体积,w[N]物品的价值
int 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 = m;j >= v[i];j--){
f[j] = max(f[j],f[j - v[i]] + w[i]);
}
cout << f[m] << endl;
return 0;
}
2.完全背包
N个物品,背包体积为V,每件物品有无限个。
1.朴素写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m;
int v[N],w[N];
int 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 = 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] << endl;
return 0;
}
2.优化写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m;
int v[N],w[N];
int 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]);
}
cout << f[m] << endl;
return 0;
}
3.多重背包
1.朴素写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n,m;
int v[N],w[N],s[N];
int f[N][N];
int main(){
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 <= s[i] && 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] << endl;
return 0;
}
2.二进制优化写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 25000,M = 2010;
int n,m;
int v[N],w[N];
int f[N];
int main(){
cin >> n >> m;
int cnt = 0;
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;
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] << endl;
return 0;
}
4.分组背包
优化写法
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n,m;
int v[N][N],w[N][N],s[N];
int f[N];
int main(){
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> s[i];
for(int j = 0;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] << endl;
return 0;
}