多重背包II中的二进制拆分
for(int i=1;i<=n;i++)
{
int a,b,s;cin>>a>>b>>s;//体积、价值、数量
int k=1;
while(k<=s)
{
w[++cnt]=a*k,v[cnt]=b*k;
s-=k;
k*=2;
}
// cout<<"s=="<<s<<endl;
if(s)
w[++cnt]=a*s,v[cnt]=b*s;
}
y总的混合背包(精简的二进制拆分)
#include <iostream>
using namespace std;
const int N = 1010;
int n, m;
int f[N];
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i ++ )
{
int v, w, s;
cin >> v >> w >> s;
if (!s)
{
for (int j = v; j <= m; j ++ )
f[j] = max(f[j], f[j - v] + w);
}
else
{
if (s == -1) s = 1;
for (int k = 1; k <= s; k *= 2)
{
for (int j = m; j >= k * v; j -- )
f[j] = max(f[j], f[j - k * v] + k * w);
s -= k;
}
if (s)
{
for (int j = m; j >= s * v; j -- )
f[j] = max(f[j], f[j - s * v] + s * w);
}
}
}
cout << f[m] << endl;
return 0;
}
金明的预算方案中十分有借鉴意义的二进制枚举方法
for (int i = 1; i <= n; i ++ )
for (int u = m; u >= 0; u -- )
{
for (int j = 0; j < 1 << servent[i].size(); j ++ )//2^n(n是附件的个数)种方案,从0~2^n-1
{
int v = master[i].v, w = master[i].w;
for (int k = 0; k < servent[i].size(); k ++ )//位运算枚举 2的n次方-1二进制表示有n位,从最高位开始枚举可以右移
// 0~n-1位
if (j >> k & 1)
{
v += servent[i][k].v;
w += servent[i][k].w;
}
if (u >= v) f[u] = max(f[u], f[u - v] + w);
}
}