您的位置:首页 > 其它

[HDU 5445]Food Problem[多重背包]

2015-10-12 20:13 267 查看
题目链接:[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: