目录
一、01背包(一维滚动数组)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n,m;
int v[N],w[N];
int dp[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> m >> n;
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 --)
dp[j] = max(dp[j] , dp[j - v[i]] + w[i]);
cout <<dp[m];
return 0;
}
二、完全背包(一维滚动数组)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n,m;
int v[N],w[N];
int dp[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> m >> n;
for(int i = 1; i <= n; i ++) cin >> w[i] >> v[i];
for(int i = 1; i <= n; i ++)
for(int j = v[i]; j <= m; j ++)
dp[j] = max(dp[j] , dp[j - v[i]] + w[i]);
cout <<dp[m];
return 0;
}
三、多重背包
---朴素版(一维滚动数组)
时间复杂度 o(n*m*s)
#include<iostream>
using namespace std;
const int N = 1e2+10;
int dp[N];
int n,m;
int v[N],w[N],s[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 = m; j >= v[i]; j --)
for(int k = 1; k <= s[i] && k * v[i] <= j ; k ++)
dp[j] = max(dp[j] , dp[j - v[i]*k] + k * w[i]);
cout << dp[m] ;
return 0;
}
---二进制优化(一维滚动数组)
时间复杂度o(n*m*log(s))
朴素版:枚举每个s[i] 将每个s[i]拆成01背包
二进制优化:枚举s[i]的二进制数 每个十进制数都能拆成二进制的和
eg:7 = 1 + 2 + 4
10 = 1 + 2 + 4 + 3 (c)
2^0 2^1 2^2 ... 2^k 相加为 2^(k+1) - 1 ====> 0(B) 10 100 1000 相加为 1111 10000 - 1
当 当前枚举的二进制数相加 = 2^(k+1) < s[i] - 2^(k+1) -1时结束 最后将常数c补在最后
#include<iostream>
using namespace std;
const int M = 2100, N = 12000; // 1000 * log(2000)
int dp[M];
int n,m;
int v[N],w[N],cnt;
int main(){
cin >> n >> m;
for(int i = 1 ; i <= n; i ++)
{
int a,b,s;
cin >> a >> b >> s;
int k = 1;
while(k <= s)
{
cnt++;
v[cnt] = k * a;
w[cnt] = k * b;
s -= k;
k <<= 1;
}
if(s > 0)
{
cnt ++;
v[cnt] = s * a;
w[cnt] = s * b;
}
}
for(int i = 1 ; i <= cnt; i ++)
for(int j = m ; j >= v[i] ; j --)
dp[j] = max(dp[j] , dp[j-v[i]] + w[i]);
cout<<dp[m];
return 0;
}