01背包
最大价值
背包数量为 \(V\),有 \(n\)件物品,重量为 \(w_i\),价值为 \(c_i\)。求能获得最大价值。
ll V, n, w[10000], c[10000], f[10000];
int main()
{
V = read();
n = read();
for (int i = 1; i <= n; ++i)
{
w[i] = read();
c[i] = read();
}
for (int i = 1; i <= n; ++i)
for (int v = V; v >= w[i]; --v)
{
if (f[v - w[i]] + c[i] > f[v])
f[v] = f[v - w[i]] + c[i];
}
printf("%lld\n", f[V]);
return 0;
}
方案数
一种物品只能选一次,组合出固定价值的方案数问题。
例题:ybt1291:数字组合
ll a[21], f[1003], n, t;
int main()
{
n = read();
t = read();
for (int i = 1; i <= n; ++i)
{
a[i] = read();
}
f[0] = 1;
for (int i = 1; i <= n; ++i)
{
for (int j = t; j >= a[i]; --j)
{
f[j] += f[j - a[i]];
}
}
printf("%lld\n", f[t]);
return 0;
}
完全背包
最大价值
一种物品可以选无限次。
只需要改一下第二层循环的循环顺序就行了。
for (int i = 1; i <= n; ++i)
for (int v = w[i]; v <= V; ++v)
{
if (f[v - w[i]] + c[i] > f[v])
f[v] = f[v - w[i]] + c[i];
}
方案数
一种物品可以选无限次,组合出固定价值的方案数问题。
例题:ybt1293:买书
ll a[5], f[10002], m;
int main()
{
m = read();
a[1] = 10, a[2] = 20, a[3] = 50, a[4] = 100;
f[0] = 1;
for (int i = 1; i <= 4; ++i)
{
for (int j = a[i]; j <= m; ++j)
{
f[j] += f[j - a[i]];
}
}
printf("%lld\n", f[m]);
return 0;
}
混合背包
一种物品可以选 \(p\) 次。
ll w[31], c[31], p[31];
ll f[201], n, m;
int main()
{
m = read();
n = read();
for (int i = 1; i <= n; ++i)
{
w[i] = read();
c[i] = read();
p[i] = read();
}
for (int i = 1; i <= n; ++i)
{
if (p[i] == 0) //完全
{
for (int j = w[i]; j <= m; ++j)
f[j] = max(f[j], f[j - w[i]] + c[i]);
}
else //01和多重
{
for (int j = 1; j <= p[i]; ++j)
{
for (int k = m; k >= w[i]; --k)
{
f[k] = max(f[k], f[k - w[i]] + c[i]);
}
}
}
}
printf("%lld\n", f[m]);
return 0;
}
二维费用背包
再加一重循环,多开一维数组即可。
ll v, u, k;
ll a[1091], b[1021], c[1092];
ll f[101][101];
int main()
{
memset(f, 127, sizeof f);
f[0][0] = 0;
v = read();
u = read();
k = read();
for (int i = 1; i <= k; ++i)
{
a[i] = read();
b[i] = read();
c[i] = read();
}
for (int i = 1; i <= k; ++i)
{
for (int j = v; j >= 0; --j)
{
for (int l = u; l >= 0; --l)
{
ll t1 = j + a[i];
ll t2 = l + b[i];
t1 = min(t1, v);
t2 = min(t2, u);
f[t1][t2] = min(f[t1][t2], f[j][l] + c[i]);
}
}
}
printf("%lld\n", f[v][u]);
return 0;
}