Magry的朋友很多 - 零食篇
题目描述
Magry有个好朋友Ricardo快要过生日了。Ricardo突然想到可以借生日坑蒙拐骗
点东西出来,于是就找了Magry要他买零食当生日礼物。
Magry手上没那么多钱,不过想了想还是上了天猫超市搜了一波,被那么多吃的看的眼花缭乱头晕目眩不知所措,因为Ricardo只有一个要求,那就是东西尽量好吃,而且还不要有Ricardo不喜欢的东西。。。
Magry已经知道的是:卖的零食总共有n种,不过比较坑爹的是一种零食一个用户限购一件;每种商品的价格为x元,好吃程度为w。另外,Magry已经知道在那些零食中有一部分是Ricardo不喜欢的(也许是忌口,总之这个和零食的好吃程度毫无关联,甚至对于一部分好吃程度为0甚至是负数的黑暗料理Ricardo也很有可能喜欢吃)。然后,Magry身上总共只有k元。
现在,Magry想要的是:如何确定购买方案使得在Magry手上的k元不会被透支(即商品总额不大于k元)的情况下买到总的好吃程度最高并且没有Ricardo不喜欢的零食呢?
时间很急很关键,亲们快帮他一把!(另请注意Hint很关键一定要看~)
输入
多组测试数据。
每组数据第一行为一个数,为商品种类数n, 0≤n≤10000
接下来n行,每行3个整数x,w,t,每行分别表示一种商品,x代表商品价格,w代表东西的好吃程度,t表示Ricardo喜不喜欢这个东西,1表示喜欢,0表示不喜欢。其中 1≤x≤1000 ,w在int范围内。
还有最后一行,一个数,k,表示Magry手头的钱。 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到停不下来,建议如下:
- 使用if条件语句比较而不用min(), max()等函数及类似ans=a>b?a:b这类条件传送语句;
- 尽量避免使用乘法。
解析:
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");
}
}
}