背包小记
贴个代码
01背包
倒序枚举
#include <bits/stdc++.h>
using namespace std;
const int M = 1e4+15;
int dp[M];
int main(){
int m,n;scanf("%d%d",&m,&n);
for(int i = 1 ; i<=n ; i++){
int w,v;scanf("%d%d",&w,&v);
for(int j = m ; j>=w ; j--) dp[j] = max(dp[j],dp[j-w]+v);
}
printf("%d",dp[m]);
return 0;
}
完全背包
#include <bits/stdc++.h>
using namespace std;
const int M = 1e7+15;
long long dp[M];
int main(){
int m,n;scanf("%d%d",&m,&n);
for(int i = 1 ; i<=n ; i++){
int w,v;scanf("%d%d",&w,&v);
for(int j = w ; j<=m ; j++) dp[j] = max(dp[j],dp[j-w]+v);
}
printf("%lld",dp[m]);
return 0;
}
多重背包二进制拆分
#include <bits/stdc++.h>
using namespace std;
const int M = 2e6+15;
int n,m,v[M],w[M],cnt,dp[M];
int main(){
scanf("%d%d",&n,&m);
for(int i = 1 ; i<=n ; i++){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
for(int j = 1 ; j<=c ; j<<=1) v[++cnt] = a*j,w[cnt] = b*j , c-=j;
if(c) v[++cnt]=a*c,w[cnt]=b*c;
}
for(int i = 1 ; i<=cnt ; i++)
for(int j = m ; j>=w[i] ; j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("%d",dp[m]);
return 0;
}
分组背包
#include <bits/stdc++.h>
using namespace std;
const int N = 1015;
int n,m,w[N][N],v[N][N],c[N],dp[N];
int main(){
scanf("%d%d",&m,&n);
for(int i = 1 ; i<=n ; i++){
int a,b,x;scanf("%d%d%d",&a,&b,&x);
w[x][++c[x]] = a , v[x][c[x]] = b;
}
for(int i = 1 ; i<=n ; i++)
for(int j = m ; j>=0 ; j--)
for(int k = 1 ; k<=c[i] ; k++)
if(j>=w[i][k])
dp[j] = max(dp[j],dp[j-w[i][k]]+v[i][k]);
printf("%d",dp[m]);
return 0;
}

浙公网安备 33010602011771号