0/1背包问题,就是给n种石头每块石头的价值为ai,问背包容量为m的背包最多装价值多少?
输入样例:
3 8
2 5 5
3 4 5
输出:8
因为不能重复选,所以这次价格的的最大应该是dp[i-1]
#include
#include
#include
using namespace std;
int dp[500][500];
int cost[500];
int weight[500];
int main(){
freopen("in.txt","r",stdin);
int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m;
cin >> n >> m;
memset(weight,0,sizeof(weight));
memset(cost,0,sizeof(cost));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++){
cin >> weight[i];
}
for(i=1;i<=n;i++){
cin >> cost[i];
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(j>=weight[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+cost[i]);
else
dp[i][j]=dp[i-1][j];
//cout << dp[i][j] << " ";
}
//cout << endl;
}
cout << dp[n][m] << endl;
}
完全背包问题:就是有n种石头无限多个,每个的重量为a价值为bii,问背包为m的背包最多装价值多少的石头
输入样例
5 35输出 103
因为能重复选,所以这次价格的的最大应该是max(dp[i-1][j],dp[i][j-weight[i]]+cost[i])!!注意原来是dp[i-1][j]
#include
#include
#include
using namespace std;
int dp[500][500];
int cost[500];
int weight[500];
int main(){
freopen("in.txt","r",stdin);
int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m;
cin >> n >> m;
memset(weight,0,sizeof(weight));
memset(cost,0,sizeof(cost));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++){
cin >> weight[i] >>cost[i];
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(j>=weight[i])
dp[i][j]=max(dp[i-1][j],dp[i][j-weight[i]]+cost[i]);
else
dp[i][j]=dp[i-1][j];
// cout << dp[i][j] << " ";
}
// cout << endl;
}
cout << dp[n][m] << endl;
多重背包问题:
有N个石头,每个有ai个,价值分别为bi,重量为ci,问M的背包最多装多少价值?
输入样例:
10 20
2 100 4
4 100 2
5 100 6
6 100 8
10 100 5
20 100 2
15 50 3
12 60 4
11 80 6
20 90 5
输出:600
用0/1背包的问题,一个石头多种的就分别当作不同的石头,o(N*a[i])
#include
#include
#include
using namespace std;
int dp[500][500];
int value[500];
int weight[500];
int ds[500];
int main(){
freopen("in.txt","r",stdin);
int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m;
cin >> n >> m;
memset(weight,0,sizeof(weight));
memset(value,0,sizeof(value));
memset(ds,0,sizeof(ds));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++){
cin >> weight[i] >> value[i] >> ds[i];
}
t1=0;
for(i=1;i<=n;i++){
for(k=1;k<=ds[i];k++){
t1++;
for(j=1;j<=m;j++){
if(j>=weight[i])
dp[t1][j]=max(dp[t1-1][j],dp[t1-1][j-weight[i]]+value[i]);
else
dp[t1][j]=dp[t1-1][j];
//cout << dp[t1][j] << " ";
}
//cout << endl;
}
}
cout << dp[t1][m] << endl;
}
用二进制加速
如一块石头有18个,因为是1个个加到dp[i][j]的j上,速度很慢,如果将其分为1、2、4、8、4那么这5个数字的组合是可以得到1-18的任意数的,也就是可以把18个石头变成5种石头,背包的1-m重量加这5个石头或者18个石头一个个加的意义是一样的。
这样的复杂度变成O(N*loga[i])
#include
#include
#include
#include
using namespace std;
int dp[500][500];
int value[500];
int weight[500];
int ds[500];
int ds2[500];
int main(){
freopen("in.txt","r",stdin);
int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m;
cin >> n >> m;
memset(weight,0,sizeof(weight));
memset(value,0,sizeof(value));
memset(ds,0,sizeof(ds));
memset(dp,0,sizeof(dp));
memset(ds2,0,sizeof(ds2));
for(i=1;i<=n;i++){
cin >> weight[i] >> value[i] >> ds[i];
}
for(i=1;i<=n;i++){
t1=ds[i];
k=0;
// cout <=ds2[k]*weight[i])
dp[t1][j]=max(dp[t1-1][j],dp[t1-1][j-ds2[k]*weight[i]]+ds2[k]*value[i]);
else
dp[t1][j]=dp[t1-1][j];
//cout << dp[t1][j] << " ";
}
//cout << endl;
}
}
cout << dp[t1][m] << endl;
}