01背包问题
一个物品要么放入背包,要么就不放入背包,在背包容量有限的情况下得到最大的价值(权重)
状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-ci]+wi)
dp[i][j]表示加入第i个物品后容量为j的最大价值,=max(不加入第i个物品的价值,加入第i个物品的价值)
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<math.h>
#include<iomanip>
#include<map>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define ll long long int
using namespace std;
const int N = 25;
int dp[N][N];
int c[N];
int w[N];
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
int i,j;
int v,n;
cin>>v>>n;
for(i=1;i<=n;i++){
cin>>c[i]>>w[i];
}
//初始状态
//当背包容量为0时,价值为0、当背包里面没有物品时,价值同样为0;
for(i=0;i<=N;i++){
dp[i][0]=0;
dp[0][i]=0;
}
int maxx=0;
for(i=1;i<=n;i++){//放入第i个物品后 最大容量的最优解
for(j=1;j<=v;j++){
if(j<c[i])
dp[i][j]=dp[i-1][j];
dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
}
}
cout<<dp[n][v]<<endl;
//get_loaction
/*
j=v;
for(i=n;i>0;i--){
if(dp[i][j]>dp[i-1][j]){
cout<<i<<' ';
j-=c[i];
}
}
cout<<"\n";
*/
return 0;
}
01背包问题的优化
在01背包问题的基础上进行优化,因为每加入一个物品,dp[][]都是从左往右,从上到下进行计算的,即当计算第i个物品时,它只与第i-1个物品相关,可以用一维的dp[]从右往左计算,简单的设想一下放入0个物品时,dp[]={0,0,0,0,0,0};当放入1个物品(weight=2,value=2)后dp[]={0,0,2,2,2,2},放入第2个物品(weight=3,4) dp[]={0,0,2,3,3,6},依次类推,右边的值只和左边的值有关,而左边的值是上一次更新过的。
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<math.h>
#include<iomanip>
#include<map>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define ll long long int
using namespace std;
const int N = 25;
int dp[N]={0};
int c[N];
int w[N];
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
int i,j;
int v,n;
cin>>v>>n;
for(i=1;i<=n;i++){
cin>>c[i]>>w[i];
}
for(i=1;i<=n;i++){
for(j=v;j>=c[i];j--){
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
}
}
cout<<dp[v]<<endl;
return 0;
}
完全背包
与01背包类似,但是每个物品时无限的
核心代码
for(i=1;i<=n;i++){
for(j=c[i];j<=v;j++){
dp[i][j]=dp[i-1][j];
for(int k=1;k*c[i]<=j;k++){
dp[i][j]=max(dp[i][j],dp[i-1][j-k*c[i]]+w[i]);
}
}
}
}
分组背包
与01背包问题类似,但是每个物品都有固定的分组,每组内的物品互斥,即每组最多只能取一个物品。
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<math.h>
#include<iomanip>
#include<map>
#include<stack>
#include<queue>
#include<set>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define mkp make_pair
#define ll long long int
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int N = 1e3+10;
int a[N]={0},b[N]={0},c[N]={0},p[N][N]={0};
int dp[N]={0};
int main()
{
//freopen("aa.in","r",stdin);
//freopen("aa.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int i,j,m,n,t=0;
cin>>m>>n;
for(i=1;i<=n;i++){
cin>>a[i]>>b[i]>>c[i];//体积,价值,分组
t=max(t,c[i]);//记录最大的分组
p[c[i]][0]++;//记录每组物品的数量
p[c[i]][ p[c[i]][0]]=i;
}
for(i=1;i<=t;i++){
for(int v=m;v>=0;v--){
for(j=1;j<=p[i][0];j++){
int k=p[i][j];
if(a[k]<=v)
dp[v]=max(dp[v],dp[v-a[k]]+b[k]);
}
}
}
cout<<dp[m]<<endl;
return 0;
}