zoukankan      html  css  js  c++  java
  • hdu 5445 Food Problem 多重背包

    Food Problem

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    http://acm.hdu.edu.cn/showproblem.php?pid=5445

    Description

    Few days before a game of orienteering, Bell came to a mathematician to solve a big problem. Bell is preparing the dessert for the game. There are several different types of desserts such as small cookies, little grasshoppers and tiny mantises. Every type of dessert may provide different amounts of energy, and they all take up different size of space.

    Other than obtaining the desserts, Bell also needs to consider moving them to the game arena. Different trucks may carry different amounts of desserts in size and of course they have different costs. However, you may split a single dessert into several parts and put them on different trucks, then assemble the parts at the game arena. Note that a dessert does not provide any energy if some part of it is missing.

    Bell wants to know how much would it cost at least to provide desserts of a total energy of p (most of the desserts are not bought with money, so we assume obtaining the desserts costs no money, only the cost of transportation should be considered). Unfortunately the mathematician is having trouble with her stomach, so this problem is left to you.

    Input

    The first line of input contains a integer T(T≤10) representing the number of test cases.

    For each test case there are three integers n,m,p on the first line (1≤n≤200,1≤m≤200,0≤p≤50000), representing the number of different desserts, the number of different trucks and the least energy required respectively.

    The i−th of the n following lines contains three integers ti,ui,vi(1≤ti≤100,1≤ui≤100,1≤vi≤100) indicating that the i−th dessert can provide ti energy, takes up space of size ui and that Bell can prepare at most vi of them.

    On each of the next m lines, there are also three integers xj,yj,zj(1≤xj≤100,1≤yj≤100,1≤zj≤100) indicating that the j−th truck can carry at most size of xj , hiring each one costs yj and that Bell can hire at most zj of them.

    Output

    For every test case output the minimum cost to provide the dessert of enough energy in the game arena if it is possible and its cost is no more than 50000. Otherwise, output TAT on the line instead.

    Sample Input

    4
    1 1 7
    14 2 1
    1 2 2
    1 1 10
    10 10 1
    5 7 2
    5 3 34
    1 4 1
    9 4 2
    5 3 3
    1 3 3
    5 3 2
    3 4 5
    6 7 5
    5 3 8
    1 1 1
    1 2 1
    1 1 1

    Sample Output

    4
    14
    12
    TAT

    HINT

    题意

    给你一些糖,有体积和价值和数量,糖果是可以拆分的

    然后给你一些背包,每个背包需要钱,可以装v的体积糖果,然后有k个背包

    问你最小多少花费买背包,可以获得p点价值的糖果

    题解:

    拆分糖果就把背包合在一起就好了,当成体积来做

    dp1[p]表示体积是P的最小糖果体积

    dp2[s]表示money是s时能够获得的最大体积

    需要二进制优化/单调队列优化

    代码:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <stack>
    #include <map>
    #include <set>
    #include <queue>
    #include <iomanip>
    #include <string>
    #include <ctime>
    #include <list>
    #include <bitset>
    typedef unsigned char byte;
    #define pb push_back
    #define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
    #define local freopen("in.txt","r",stdin)
    #define pi acos(-1)
    
    using namespace std;
    const int maxn = 200 + 15;
    
    struct item
    {
        int val , size;    
    };
    
    struct item2
    {
        int size , cost;    
    };
    
    int n , m , p ,sz[maxn],dp1[50000+500],sz2[maxn],dp2[50000+500];
    item2  B[maxn][55] ;
    item A[maxn][55];
    
    
    void initiation()
    {
        memset( sz , 0 ,sizeof(sz));
        memset( sz2,0,sizeof(sz2));
        scanf("%d%d%d",&n,&m,&p);
        for(int i = 1 ; i <= n ; ++ i)
        {
            int v , sq , number , cot = 0;
            scanf("%d%d%d",&v,&sq,&number);
            for(int j = 1 ; ; j <<= 1)
            {
                if(cot + j > number)
                {
                    int dcv = number - cot;
                    if(dcv != 0)
                    {
                        A[i][sz[i]].val = dcv*v;
                        A[i][sz[i]].size = dcv*sq;
                        sz[i]++;
                    }
                    break;
                }
                A[i][sz[i]].val = v*j;
                A[i][sz[i]].size = sq*j;
                sz[i]++;
                cot += j;
            }
        }
        for(int i = 1 ; i <= m ; ++ i)
        {
            int v , sq , number , cot = 0;
            scanf("%d%d%d",&v,&sq,&number);
            for(int j = 1 ; ; j <<= 1)
            {
                if(cot + j > number)
                {
                    int dcv = number - cot;
                    if(dcv != 0)
                    {
                        B[i][sz2[i]].size = dcv*v;
                        B[i][sz2[i]].cost = dcv*sq;
                        sz2[i]++;
                    }
                    break;
                }
                B[i][sz2[i]].size = v*j;
                B[i][sz2[i]].cost = sq*j;
                sz2[i]++;
                cot += j;
            }
        }
    }
    
    inline void updata(int & x,int v)
    {
        x = min(x , v);
    }
    
    inline void updata2(int & x,int v)
    {
        x = max(x , v);
    }
    
    
    void solve()
    {
        memset(dp1,0x3f,sizeof(dp1));dp1[0] = 0;
        int error = dp1[1];
        for(int i = 1 ; i <= n ; ++ i)
         {
            for(int z = 0 ; z < sz[i] ; ++ z)
             {
                for(int j = p - 1 ; j >= 0 ; -- j)
                {
                   if(dp1[j] == error ) continue;
                   int newj = j + A[i][z].val;
                   int newcost = dp1[j] + A[i][z].size;
                   if(newj >= p ) newj=p;
                   updata(dp1[newj],newcost);
                }
             }
         }
         if(dp1[p] == error)
         {
             printf("TAT
    ");
             return;
         }
         int need = dp1[p];
         memset(dp2,0,sizeof(dp2));
         for(int i = 1 ; i <= m ; ++ i)
         {
            for(int z = 0 ; z < sz2[i] ; ++ z)
            {
                int cost = B[i][z].cost;
                int size = B[i][z].size;
                for(int j = 5e4 ; j >= cost ; -- j) updata2(dp2[j] , dp2[j-cost] + size);
            }
         }
         int ans = -1;
         for(int i = 0 ; i <= 5e4 ; ++ i)
         {
            if(dp2[i] >= need) 
            {
                ans = i;
                break;
            }
         }
         if(~ans) printf("%d
    ",ans);
         else printf("TAT
    ");
    }
    
    
    int main(int argc,char *argv[])
    {
        int Case;
        scanf("%d",&Case);
        while(Case--)
        {
            initiation();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    Eric 的随机文件名 生成方法
    .NET模板引擎 EFPlatform.CodeGenerator (代码生成器 静态页生成 生成HTML 模板)
    Eric的行政区(省市)下列表控件和标签控件
    下载网页中远程图片的方法
    一起来玩Twister(扭扭乐)
    ASP.NET 安全认证(四)——巧妙实现 Form 表单认证跨站点、跨服务器的单点登录(Single Sign On) .
    DataList的编辑、更新、删除、全选、分页以及 <EditItemTemplate>模版中的DropDownList的数据绑定
    ASP.NET 安全认证(三)—— 用Form 表单认证实现单点登录(Single Sign On) .
    C# 中的委托和事件
    ASP.Net获取当前运行文件的文件名称
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4806863.html
Copyright © 2011-2022 走看看