一、01背包问题
问题描述:给定n个重量为w1,w2,……,wn;价值为v1,v2,……,vn的物品和一个能承重为W的背包。求背包能装入的最终价值最多的物品编号。
设F(I,j)为能够放进承重为j的背包的前i个物品中最有价值的子集的总价值。因此:
(1)不包括第i个物品的子集中,最优子集的价值是F(i-1,j)
(2)在包括第i个物品的子集中,最优子集总价值为vi+F(i-1,j-wi)
因此可推导出这个递推式:
F(I,j)=F(I-1,j),j-wi<0
Max{F(I-1,j),vi+F(I-1,j-wi)},j-wi>=0
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=4; //物品件数
const int W=5; //背包容量
int main()
{
int value[N+1]={0,12,10,20,15}; //物品价值
int weight[N+1] = {0,2,1,3,2}; //物品质量
int f[N+1][W+1] = {0}; // f[i][j]表示在背包容量为j的情况下, 前i件宝贝的最大价值
for(int i = 1; i <= N; i++){
for(int j = 1; j <= W; j++){
if(j < weight[i])
f[i][j] = f[i - 1][j];
else
f[i][j]=max(f[i-1][j],f[i-1][j-weight[i]]+value[i]);
}
}
for(int i=1;i<=N;i++){
for(int j=1;j<=W;j++)
cout<<f[i][j]<<" ";
cout<<endl;
}
return 0;
}
二、完全背包
每种物品无限量
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=4; //物品件数
const int W=5; //背包容量
int main()
{
int value[N+1]={0,12,10,20,15}; //物品价值
int weight[N+1] = {0,2,1,3,2}; //物品质量
int f[W+1] = {0};
for(int i = 1; i <= N; i++){
for(int j = weight[i]; j<=W; j++){
f[j]=max(f[j],f[j-weight[i]]+value[i]);
}
}
cout<<f[W]<<endl;
return 0;
}
三、多重背包问题
背包容量为10,5种物品,每种物品的数量为1,2,1,2,1;重量为5,4,3,2,1;价值为1,2,3,4,5。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=5; //物品件数
const int W=10; //背包容量
int main()
{
int value[N+1]={0,1,2,3,4,5}; //物品价值
int weight[N+1] = {0,5,4,3,2,1}; //物品质量
int number[N+1]={0,1,2,1,2,1}; //没件物品的数量
int f[W+1] = {0};
for(int i = 1; i <= N; i++){
for(int k=1;k<=number[i];k++){
for(int j = W; j>= weight[i]; j--){
f[j]=max(f[j],f[j-weight[i]]+value[i]);
}
}
}
cout<<f[W]<<endl;
return 0;
}