版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27121257/article/details/82590574
传送门:洛谷 P1417
题目描述
一共有n件食材,每件食材有三个属性,
,
和
,如果在t时刻完成第i样食材则得到
的美味指数,用第i件食材做饭要花去
的时间。
众所周知,gw的厨艺不怎么样,所以他需要你设计烹调方案使得美味指数最大
分析
由于
这一条件的限制,看起来有些无从下手.
若是能利用某些方式摆脱
的限制,那就好办了,直接01背包即可.
下面用相邻交换法证明一下如何排序使得前面处理的食物必定更优
假设当前已用时间为
,有
与
两样食物
先与
的收益
先与
的收益
两式相减,得: $ w1 - w2 = b_i \times c_j - b_j \times c_i $
对此,若令
在前更优,则
, 即 $ b_i \times c_j > b_j \times c_i $
因此,按照$ b_i \times c_j > b_j \times c_i long$
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define IL inline
using namespace std;
IL int read()
{
char c = getchar();
int sum = 0 ,k = 1;
for(;'0' > c || c > '9'; c = getchar())
if(c == '-') k = -1;
for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0';
return sum * k;
}
typedef long long ll;
struct node
{
ll x, y, z;
}num[55];
IL bool cmp(const node &a, const node &b)
{
return a.y * b.z > a.z * b.y;
}
IL ll max_(ll x, ll y) { return x > y ? x : y; }
ll f[100005];
int main()
{
int m = read(), n = read();
for(int i = 1; i <= n; ++i) num[i].x = read();
for(int i = 1; i <= n; ++i) num[i].y = read();
for(int i = 1; i <= n; ++i) num[i].z = read();
sort(num + 1, num + n + 1, cmp);
for(int i = 1; i <= n; ++i)
{
for(int j = m; j >= num[i].z; --j)
f[j] = max_(f[j], f[j - num[i].z] + num[i].x - num[i].y * j);
}
ll ans = 0;
for(int i = 0; i <= m; ++i)
ans = max_(ans, f[i]);
printf("%lld\n", ans);
return 0;
}