题目连接:https://www.luogu.com.cn/problem/P1417
思路:
因为得到物品的价值与选取物品的先后顺序有关,假设有x,y两个物品,当前时刻为t
(1)先x后y,a[x] - (t + c[x])*b[x] + a[y] - (t + c[x] + c[y])*b[y];
(2)先y后x,a[y] - (t + c[y])*b[y] + a[x] - (t + c[y] + c[x])*b[x];
化简得到(1)>(2)的条件是 b[x] * c[y] > b[y] * c[x];
所以先按照上面的条件排序,然后01背包跑一遍就好了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
struct Node{
int a,b,c;
}cur[N];
long long dp[N] = {0};
int n,T;
bool cmp(Node a,Node b){
return 1ll*a.b*b.c > 1ll*a.c*b.b;
}
int main(void)
{
scanf("%d%d",&T,&n);
for(int i=1;i<=n;i++) scanf("%d",&cur[i].a);
for(int i=1;i<=n;i++) scanf("%d",&cur[i].b);
for(int i=1;i<=n;i++) scanf("%d",&cur[i].c);
sort(cur+1,cur+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=T;j>=cur[i].c;j--)
dp[j] = max(dp[j],dp[ j - cur[i].c ] + 1ll*cur[i].a - 1ll*cur[i].b*j);
}
long long ans = dp[0];
for(int i=1;i<=T;i++) ans = max(ans,dp[i]);
printf("%lld\n",ans);
return 0;
}