目录
01背包问题
#include <iostream>
using namespace std;
const int N = 1010;
int f[N],v[N],w[N];
int n,m;
//二维背包
//int f[N][N];
/*
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i ++ ) cin >> v[i] >> w[i];
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++)
{
if (j >= v[i]) f[i][j] = max(f[i - 1][j],f[i - 1][j - v[i]] + w[i]);
else f[i][j] = f[i - 1][j];
}
cout << f[n][m];
return 0;
}
*/
//一维优化
int main()
{
cin >> n >> m;
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 --)
{
f[j] = max(f[j] , f[j - v[i]] + w[i]);
}
cout << f[m];
return 0;
}
完全背包问题
#include <iostream>
using namespace std;
const int N = 1010;
int v[N],w[N];
int n,m;
int f[N];
//一维
int main()
{
cin>> n >> m;
for(int i = 1;i <= n; i ++ ) cin >> v[i] >> w[i];
for(int i=1;i<=n;i++)
for (int j = v[i]; j <= m;j ++ )
f[j]=max(f[j],f[j-v[i]]+w[i]);
cout << f[m];
return 0;
}
/*二维版本
int f[N][N];
int main()
{
cin>> n >> m;
for(int i = 1;i <= n; i ++ ) cin >> v[i] >> w[i];
for(int i=1;i<=n;i++)
for (int j = 0; j <= m;j ++ )
{
if(j>=v[i])
//f[i][j]=max(f[i][j-v]+w,f[i][j-2v]+2w,.......);
//f[i[[j-v]=max(f[i][j-v],f[i][j-2v]+w,........);
//综上可知f[i][j] == f[i][j-v] + w
f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]);
else f[i][j]=f[i-1][j];
}
cout << f[n][m];
return 0;
}
*/
/* for(int k = 0;k * v[i] <= j;k ++ )
{
f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);//不包括第i个物品在加上第i个物品
}
*/
多重背包
#include <iostream>
using namespace std;
const int N = 25010;
int f[N];
int v[N],w[N];
int n,m;
// 优化
//思路 吧每个类型分成2^x 转换成 01 背包类型
int main()
{
cin >> n >> m;
int cnt = 0;
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 *= 2;
}
if (s>0)
{
cnt ++;
v[cnt] = s * a;
w[cnt] = s * b;
}
}
n = cnt;
for (int i = 1;i <= n;i ++ )
for (int j = m;j >= v[i];j --)
f[j] = max(f[j],f[j - v[i]] + w[i]);
cout << f[m];
return 0;
}
/*
//朴素版本,与完全背包类似
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 = 0;j <= m;j ++ )
for (int k = 0;k <= s[i] ;k ++)
{
if(j >= k * v[i])
//f[i - 1][j - k * v[i]] + k * w[i]去掉第i个物品在加上第k*i个物品的体积
f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);
}
cout << f[n][m];
return 0;
}
*/
分组背包问题
#include <iostream>
using namespace std;
const int N = 200;
int v[N][N],w[N][N],s[N];
int n,m;
//二维
int f[N][N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i ++ )
{
cin >> s[i];
for (int j = 0;j < s[i];j ++ )
{
int a,b;
cin >> a >> b;
v[i][j] = a,w[i][j] = b;
}
}
for (int i = 1;i <= n;i ++ )
for (int j = 0;j <= m;j ++ )
{
f[i][j] = f[i - 1][j];
for (int k = 0;k < s[i];k ++ )
{
if(v[i][k] <= j)
f[i][j] = max(f[i][j],f[i - 1][j - v[i][k]] + w[i][k]);
}
}
cout << f[n][m];
return 0;
}
/*一维
int f[N];
int main()
{
cin >> n >> m;
for (int i = 1;i <= n;i ++ )
{
cin >> s[i];
for (int j = 0;j < s[i];j ++ )
{
int a,b;
cin >> a >> b;
v[i][j] = a,w[i][j] = b;
}
}
for (int i = 1;i <= n;i ++ )
for (int j = m;j >= 0;j -- )
{
for (int k = 0;k <s[i];k++)
{
if(v[i][k] <= j )
f[j] = max(f[j],f[j - v[i][k]] + w[i][k]);
}
}
cout << f[m];
return 0;
}
*/
混合背包问题
//思路转换成多重背包
#include <iostream>
using namespace std;
const int N = 100100;
int f[N],v[N],w[N];
int n,m;
int main()
{
cin >> n >> m;
int cnt = 0;
for (int i = 1;i <= n;i ++ )
{
int a,b,s;
cin >> a >>b >>s;
int k = 1;
if(s < 0) s = 1;
else if (s==0) s = m/a;
while(k <= s){
cnt ++;
v[cnt] =k * a;
w[cnt] =k * b;
s -= k;
k *=2;
}
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 --)
{
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
cout <<f[m];
return 0;
}