最好的方案(dp,一个好用技巧)

第4题     最好的方案 查看测评数据信息

Jane是一位富有冒险精神的火星人,他驾驶着自己的飞船穿越星际,向传说中的地球进发。然而,在飞船穿越茫茫宇宙的旅途中,Jane的肚子开始抗议了。幸运的是,Jane是一位热爱烹饪的星际旅行者,他拿出了飞船上储藏的食材,打算为自己做一顿大餐。

但是,Jane很快发现,这些食材的美味程度并不是固定的,而是与烹饪完成的时间有关。每件食材都有三个关键的属性:

a[i]:表示食材的初始美味值。

b[i]:表示食材的美味值随时间衰减的速率(即每过一秒,美味值减少b[i])。

c[i]:表示烹饪这种食材所需的时间。

Jane想要在飞船到达地球前的 T 时间内,通过合理安排食材的烹饪顺序和时间,使得最终获得的美味指数最大。然而,Jane的厨艺并不精湛,他向你这位厨艺高超的星际厨师求助,希望你能帮他解决这个问题。

输入格式

 

第一行是两个正整数 T 和 n,表示到达地球所需时间和食材个数。

下面一行 n 个整数,a[i];

下面一行 n 个整数,b[i];

下面一行 n 个整数,c[i]。

对于 100 的数据 1 <= n <= 50,所有数字均小于 10^5

 

输出格式

 

输出最大美味指数。

 

输入/输出例子1

输入:

74 1

502

2

47

 

输出:

408

 

样例解释

 

有先后关系可以尝试列式子,做差法

如果没有b[i]这个属性的话就是明显的01背包问题。

现在考虑相邻的两个物品x,y。假设现在已经耗费p的时间,那么分别列出先做x,y的代价:

a[x]-(p+c[x])*b[x]+a[y]-(p+c[x]+c[y])*b[y] (①)

a[y]-(p+c[y])*b[y]+a[x]-(p+c[y]+c[x])*b[x] (②)

对这两个式子化简,得到①>②的条件是c[x]*b[y]<c[y]*b[x].

发现只要满足这个条件的物品对(x,y),x在y前的代价永远更优。

因此可以根据这个条件进行排序,之后就是简单的01背包了。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=55, M=1e5+5;

struct node
{
	int a, b, c;
}a[N];
int t, n, f[M], ans=0;
bool cmp(node a, node b)
{
	return (a.c*b.b)<(b.c*a.b);
}
signed main()
{
	scanf("%lld%lld", &t, &n);
	for (int i=1; i<=n; i++) scanf("%lld", &a[i].a);
	for (int i=1; i<=n; i++) scanf("%lld", &a[i].b);
	for (int i=1; i<=n; i++) scanf("%lld", &a[i].c);
	
	sort(a+1, a+1+n, cmp);
	
	for (int i=1; i<=n; i++)
		for (int j=t; j>=a[i].c; j--)
			f[j]=max(f[j], f[j-a[i].c]+a[i].a-j*a[i].b);
	
			
	
	for (int i=0; i<=t; i++) ans=max(ans, f[i]);
	
	printf("%lld", ans);
	return 0;
}

 

 

 

 

 

 

 

 

posted @ 2024-08-21 11:23  cn是大帅哥886  阅读(11)  评论(0)    收藏  举报