题目链接:[HDU 5445]Food Problem[多重背包]
题意分析:
有n种类型的点心,每种提供t的能量,占据u的空间,有v个;
有m种类型的卡车,每种容量x,雇佣花费y,能提供z辆;
点心可以被拆分到不同的车运送,但是必须保证点心的完整,雇佣花费不得超过5e4,问:
提供至少p能量的点心,最少需要花多少钱?否则输出『TAT』。
解题思路:
可以先用多重背包求出满足p能量的点心最少需要多少空间,再求达到至少空间最少要花费多少钱,答案就出来了。
个人感受:
看思路也不难,但是就是想不到,历练太少了ORZ。
具体代码如下:
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int INF = 0x7f7f7f7f;
const int MAXN = 6e4 + 111;
int cost[MAXN], space[MAXN], t[300], u[300], v[300], x[300], y[300], z[300];
int main()
{
int kase, n, m, p; scanf("%d", &kase);
while (kase --)
{
int mxv = 0;
scanf("%d%d%d", &n, &m, &p);
for (int i = 0; i < n; ++i) scanf("%d%d%d", &t[i], &u[i], &v[i]);
for (int i = 0; i < m; ++i)
{
scanf("%d%d%d", &x[i], &y[i], &z[i]);
mxv += x[i] * z[i];
}
// 达到p以上最少的空间
memset(cost, 0x7f, sizeof(int)*(p + 110));
cost[0] = 0;
int mxP = p + 100, minv = INF;
for (int i = 0; i < n; ++i)
{
int k = 1;
while (k < v[i])
{
for (int j = mxP; j >= k * t[i]; --j)
{
cost[j] = min(cost[j], cost[j - k * t[i]] + k * u[i]);
if (j >= p) minv = min(minv, cost[j]);
}
v[i] -= k;
k <<= 1;
}
for (int j = mxP; j >= v[i] * t[i]; --j)
{
cost[j] = min(cost[j], cost[j - v[i] * t[i]] + v[i] * u[i]);
if (j >= p) minv = min(minv, cost[j]);
}
}
if (minv > mxv)
{
puts("TAT");
continue;
}
// 因为相比于空间,费用少于5e4,所需数组小,所以采用space来统计空间,下标即为花费
memset(space, 0, sizeof space);
int minc = INF;
for (int i = 0; i < m; ++i)
{
int k = 1;
while (k < z[i])
{
for (int j = 5e4; j >= k * y[i]; --j)
{
space[j] = max(space[j], space[j - k * y[i]] + k * x[i]);
if (space[j] >= minv) minc = min(minc, j);
}
z[i] -= k;
k <<= 1;
}
for (int j = 5e4; j >= z[i] * y[i]; --j)
{
space[j] = max(space[j], space[j - z[i] * y[i]] + z[i] * x[i]);
if (space[j] >= minv) minc = min(minc, j);
}
}
if (minc > 5e4) puts("TAT");
else printf("%d\n", minc);
}
return 0;
}