hdu5445 || 2015長春網路賽1009題 多重揹包問題

life4711發表於2015-09-25

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

Problem 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(T10) representing the number of test cases.

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

The ith of the n following lines contains three integers ti,ui,vi(1ti100,1ui100,1vi100) indicating that the ith dessert can provide tienergy, 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(1xj100,1yj100,1zj100) indicating that the jth 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
/**
hdu5445 || 2015長春網路賽1009題   多重揹包問題
題目大意:給一場運動會提供食物,每種食物提供ti能量,佔用vi空間,最多可提供ui個,把食物運到指定地點,每種車可以運送ai體積的
          食物,消耗bi的金錢,總共有ci個這種車,問給運動會提供至少p的能量,最少需要花多少運費
          特別說明:每個食物可以拆開來運
解題思路:利用多重揹包的二進位制方案,先找出提供不少於p的能量需要多少空間V(揹包必須全部裝滿),然後求運送能力大於V的最小揹包
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100500;
int n,m,p;
int c[maxn],w[maxn],dp[maxn];

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        int nn=0,t,u,v;
        for(int i=0; i<n; i++)
        {
            scanf("%d%d%d",&t,&u,&v);
            int k=0;
            while(v-(1<<(k+1))+1>0)k++;
            for(int j=0; j<k; j++)
            {
                ++nn;
                c[nn]=t*(1<<j);
                w[nn]=u*(1<<j);
            }
            ++nn;
            c[nn]=t*(v-(1<<k)+1);
            w[nn]=u*(v-(1<<k)+1);
        }
        memset(dp,0x3f3f3f3f,sizeof(dp));
        dp[0]=0;
        for(int i=1; i<=nn; i++)
        {
            for(int j=p+100; j>=c[i]; j--)//單個食物提供能量最大100,因此我們找p~p+100之間的完全裝滿的最小體積
            {
                dp[j]=min(dp[j],dp[j-c[i]]+w[i]);
            }
        }
        int V=0x3f3f3f3f;
        for(int i=p; i<=p+100; i++)V=min(dp[i],V);
        nn=0;
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&u,&t,&v);
            int k=0;
            while(v-(1<<(k+1))+1>0)k++;
            for(int j=0; j<k; j++)
            {
                ++nn;
                c[nn]=t*(1<<j);
                w[nn]=u*(1<<j);
            }
            ++nn;
            c[nn]=t*(v-(1<<k)+1);
            w[nn]=u*(v-(1<<k)+1);
        }
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=nn; i++)
        {
            for(int j=50000; j>=c[i]; j--)///最大體積不超過50000
            {
                dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
            }
        }
        int ans = 0x3f3f3f3f;
        for(int i=50000; i>=0; i--)
        {
            if (dp[i] >= V)///找運送體積過V的最小揹包即為答案
            {
                ans = min(ans, i);
            }
        }
        if (ans == 0x3f3f3f3f)
            puts("TAT");
        else
            printf("%d\n", ans);
    }
    return 0;
}


相關文章