HDU 5445 Food Problem

2 篇文章 0 订阅

题意:首先有n种点心,每种点心的t,u,v代表该点心每个所提供的能量,体积,数量。

  然后有m中车,每种车的x,y,z代表这种车的容量,费用,数量。

  又有一个p,问你所选的点心达到p的能量值的时候所需要的最少费用。(点心可以切割,即可以分开到每辆车里面,但是只要你选了一个,就整个点心都要放进车里)

因为点心师可以切割的,所以我们可以分两次dp,第一次先求出要达到p能量的时候需要的最小体积minv,第二次dp求就是要达到minv的的最小费用minc

还要注意的是,题目说最后的费用不能超过50000,复杂度可以接受

这里我用了类似多重背包的方法(写得挫比较慢)。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
using namespace std;
#define ll long long
#define max(a,b) a>b?a:b
const int INF = 0x3f3f3f3f;
const int MAXN = 50010;
const int N = 205;
int dp[MAXN], pd[MAXN];
struct node{
    int t,u;
    void init(int _t, int _u){
        t = _t, u =_u;
    }
}de[N*N];
struct point{
    int x,y,z;
    void init(int _x, int _y){
        x = _x, y = _y;
    }
}ca[N*N];
int main(){
    //freopen("in.txt","r",stdin);
    int T, n, m, p;
    int cot, cot2, mx, minc, minv;
    int t, u, v, x, y, z;
    scanf("%d",&T);
    while(T--){
        mx = 0;
        minv = minc =INF;
        cot  = cot2 = 0;
        memset(pd, 0, sizeof(pd));
        scanf("%d%d%d",&n,&m,&p);
        memset(dp,0x3f,sizeof(int)*(p+105));
        for(int i = 1; i <= n; i++){
            scanf("%d%d%d",&t, &u, &v);
            int k = 1;
            while(k < v){
                de[cot++].init(k*t, k*u);
                v -= k;
                k *= 2;
            }
            if(v)de[cot++].init(v*t, v*u);
        }
        dp[0] = 0;
        //第一次DP找出能达到p能量的最小体积
        for(int i = 0; i < cot; i++){
            for(int j = p+100; j >= de[i].t; j--){
                dp[j] = min(dp[j], dp[j - de[i].t] + de[i].u);
                if(j >= p){
                    if(minv > dp[j]){
                        minv = dp[j];
                    }
                }
            }
        }
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d",&x, &y, &z);
            int k = 1;
            mx += x*z;
            while(k < z){
                ca[cot2++].init(x*k,y*k);
                z -= k;
                k *= 2;
            }
            if(z)ca[cot2++].init(x*z,y*z);
        }
        if(mx < minv){
            puts("TAT");
            continue;
        }
        //第二次DP找出能达到最小体积的最小费用
        for(int i = 0; i < cot2; i++){
            for(int j = 50000; j >= ca[i].y; j--){
                pd[j] = max(pd[j], pd[j-ca[i].y] + ca[i].x);
                if(pd[j] >= minv){
                    minc = min(minc,j);
                }
            }
        }
        if(minc<=50000)printf("%d\n",minc);
        else puts("TAT");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值