HDU 5445 Food Problem

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  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(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

背包二进制优化

#include<cstdio>
#include<cstring>
#include<ctime>
#include<algorithm>
using namespace std;
const int maxn = 100001;
int n,T,f[maxn],m,p;

struct cake
{
    int x,y,z;
    void read(){scanf("%d%d%d",&x,&y,&z);}
}a[maxn];

int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        memset(f,-1,sizeof(f));
        f[0]=0;
        int flag=1,ans;
        for (int i=0;i<n;i++) 
        {
            a[i].read();
            int u,v;
            for (int j=1;j<=a[i].z;j<<=1)
            {
                a[i].z-=j;
                u=a[i].x*j;
                v=a[i].y*j;
                for (int k=p+100;k>=u;k--)
                if (f[k-u]>=0)
                {
                    if (f[k]>=0) f[k]=min(f[k],f[k-u]+v);
                    else f[k]=f[k-u]+v;
                }
            }
            if (a[i].z)
            {
                u=a[i].x*a[i].z;
                v=a[i].y*a[i].z;
                for (int k=p+100;k>=u;k--)
                if (f[k-u]>=0)
                {
                    if (f[k]>=0) f[k]=min(f[k],f[k-u]+v);
                    else f[k]=f[k-u]+v;
                }
            }
        }
        ans=-1;
        for (int i=p;i<=p+200;i++)
        {
            if (ans==-1) ans=f[i];
            if (f[i]!=-1) ans=min(ans,f[i]);
        }
        if (ans==-1) flag=0;
        if (flag) {
            memset(f,0,sizeof(f));
            p=50000;
        }
        for (int i=0;i<m;i++) 
        {
            a[i].read();
            if (!flag) continue;
            int u,v;
            for (int j=1;j<=a[i].z;j<<=1)
            {
                a[i].z-=j;
                u=a[i].y*j;
                v=a[i].x*j;
                for (int k=p;k>=u;k--) f[k]=max(f[k],f[k-u]+v);
            }
            if (a[i].z)
            {
                u=a[i].y*a[i].z;
                v=a[i].x*a[i].z;
                for (int k=p;k>=u;k--) 
                {
                    f[k]=max(f[k],f[k-u]+v);
                    if (f[k]>=ans) p=k;
                }
            }
        }
        if (flag)
            for (int i=0;i<=p;i++) 
                if (f[i]>=ans) {ans=i; flag=1; break;}
                else flag=0;    
        if (flag) printf("%d\n",ans);
        else printf("TAT\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值