[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;
}
题意分析:
有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;
}
相关文章推荐
- 什么是系统瓶颈
- 并查集入门水题练习
- codevs 1519 过路费
- C++ STL学习笔记七 set容器
- 反射和内省比较
- JSON -- c语言,数据交换
- 基于xslt的简单应用开发
- BroadCastReceiver的创建与使用
- C++ STL学习笔记六 bit_vector位向量容器
- 安装 Xposed for Lollipop 之前,你需要知道的 4 个注意事项
- iOS 搭建Apache服务器(10.10系统)
- [LeetCode]21. 3Sum三者之和
- C++ STL学习笔记五 slist单向链表容器
- 使用OnTouchListener监听滑动事件
- 每周一刷——从斐波那契数列到动态规划
- 使用TortoiseSVN进行论文版本管理
- 自定义UI的基本结构
- Idea中Tomcat启动时日志乱码
- 1011. A+B和C (15)
- 实现类似于百度实时搜索将结果在下拉框中显示的功能