474 Magry的朋友很多 - 零食篇

Magry的朋友很多 - 零食篇

时间限制: 1500 ms 内存限制: 204800 kb
总通过人数: 136 总提交人数: 154

题目描述

Magry有个好朋友Ricardo快要过生日了。Ricardo突然想到可以借生日坑蒙拐骗点东西出来,于是就找了Magry要他买零食当生日礼物。

Magry手上没那么多钱,不过想了想还是上了天猫超市搜了一波,被那么多吃的看的眼花缭乱头晕目眩不知所措,因为Ricardo只有一个要求,那就是东西尽量好吃,而且还不要有Ricardo不喜欢的东西。。。

Magry已经知道的是:卖的零食总共有n种,不过比较坑爹的是一种零食一个用户限购一件;每种商品的价格为x元,好吃程度为w。另外,Magry已经知道在那些零食中有一部分是Ricardo不喜欢的(也许是忌口,总之这个和零食的好吃程度毫无关联,甚至对于一部分好吃程度为0甚至是负数的黑暗料理Ricardo也很有可能喜欢吃)。然后,Magry身上总共只有k元。

现在,Magry想要的是:如何确定购买方案使得在Magry手上的k元不会被透支(即商品总额不大于k元)的情况下买到总的好吃程度最高并且没有Ricardo不喜欢的零食呢?

时间很急很关键,亲们快帮他一把!(另请注意Hint很关键一定要看~)

输入

多组测试数据。

每组数据第一行为一个数,为商品种类数n, 0n10000 0≤n≤10000

接下来n行,每行3个整数x,w,t,每行分别表示一种商品,x代表商品价格,w代表东西的好吃程度,t表示Ricardo喜不喜欢这个东西,1表示喜欢,0表示不喜欢。其中 1x1000 1≤x≤1000,w在int范围内。

还有最后一行,一个数,k,表示Magry手头的钱。 0k100000 0≤k≤100000

输出

对于每组数据,输出一行,一个数,表示Magry在手头的k元不被透支的情况下所购商品的最大好吃程度。

输入样例

2
3 61 1
7 101 0
100
1
10 1 0
2

输出样例

61
0

Hint 1(重要!)

作为生日礼物,Magry可是不情愿买好吃程度为0或者负值的黑暗料理的

所以,碰见满满的零食列表,面对某些情况,Magry只好什么都不买,并且对Ricardo说:“很抱歉,我没法给你买合适的零食了。”

Hint 2

本题为防止TLE到停不下来,建议如下:

  1. 使用if条件语句比较而不用min(), max()等函数及类似ans=a>b?a:b这类条件传送语句;
  2. 尽量避免使用乘法。

解析:

01背包问题。

输入时去除不符合条件的数据,统计符合条件的零食数k,处理时,循环1到k,不然回TLE。

状态转移方程:

for(int i = V; i >= w; i--)
    {
        LL tmp = ans[i - w] + v;
        if(tmp > ans[i])
        {
            ans[i] = tmp;
        }
    }

代码:

#include<cstdio>
#include<cstring>
#define LL long long
#define maxn 10007
using namespace std;

int V;
LL Weight[maxn],Value[maxn];
LL ans[100007];

void zo_pack(int w,int v)
{
    for(int i = V; i >= w; i--)
    {
        LL tmp = ans[i - w] + v;
        if(tmp > ans[i])
        {
            ans[i] = tmp;
        }
    }
}

int main()
{
    int n,t;
    LL x,w;
    while(~scanf("%d",&n))
    {
        memset(ans,0,sizeof(ans));
        int k = 1;
        bool flag = false;
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld%lld%d",&x,&w,&t);
            if(t && w>0)
            {
                flag = true;
                Weight[k] = x;
                Value[k] = w;
                k++;
            }
        }
        scanf("%d",&V);
        if(flag)
        {
            for(int i = 1; i < k; i++)
            {
                zo_pack(Weight[i],Value[i]);
            }
            printf("%lld\n",ans[V]);
        }
        else
        {
            printf("0\n");
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值