题目链接:[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; }