目录
美食城正在举行一年一度的美食大赛。小 Q 是其中一位参赛选手,他有 个食材,第 个食材做成菜所需要的时间为 。由于新鲜度的问题,如果第 个食材在时间时才被做成菜,那么这道菜的美味度为 ,其中 和 是给定的参数。大赛时间紧张,总共只有 的时间。小 Q 想在 T 时间内做出的菜的美味度之和尽可能大,你能帮帮他吗?
第一行包含两个整数 和 。
接下来三行,每行 个数,分别表示 ~,~,~。
输出一行一个数,表示答案。
74 1
502
2
47
408
,其余所有数都不超过。
给你三个数组,代表n个食物,让你选择先后顺序,然后算出最优值。
这个题目看上去就是01背包问题,但是这不完全是01背包问题,因为它和先后顺序有关:
设有两个食物,x,y,已经耗了p的时间。
如果先煮x,再煮y。则价值为:? 设为①
如果先煮y,再煮x。则价值为:?设为②
如果想让①>②,那化简不等式:就是
所以我们根据这个排个序,再01背包就好了
我们可以边01背包,边记录答案,这样就不用枚举了。
#include<bits/stdc++.h>
using namespace std;
struct m{
long long a,b,c;//每种食物的属性
}x[100010];
int n,t;
long long dp[100010];
long long ans;
bool cmp(m a,m b)
{
return a.c*b.b<a.b*b.c;//排序
}
int main()
{
// freopen("sample (44).in","r",stdin);
cin>>t>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i].a;
}
for(int i=1;i<=n;i++)
{
cin>>x[i].b;
}
for(int i=1;i<=n;i++)
{
cin>>x[i].c;
}
sort(x+1,x+1+n,cmp);
for(int i=1;i<=n;i++)
{
for(int j=t;j>=x[i].c;j--)
{
dp[j] = max(dp[j],dp[j-x[i].c]+x[i].a-j*x[i].b);//经典的01背包转移方程
ans = max(ans,dp[j]);//边做边记录
}
}
cout<<ans;
return 0;
}