https://www.luogu.org/problemnew/show/P141
总结:
- 序列最优为dp
- 选与不选,且有sum:极有可能是背包
- 选与不选,且有sum,且物品选择的顺序也影响结果:极有可能是按照某种顺序排列后再来个背包。(怎样获得这种顺序呢?我们选两个元素,让A先发生与B后发生 和 B先发生A后发生的情况进行比较,然后就可以获得某种排序方式,本题就是这样)
看到这个题第一眼的感觉是,将其按照某种顺序排列之后,直接贪心,之前有做过类似的题。但是本题还有一个要求就是在T时间内,所以很明显是背包。但是怎样处理物品的顺序问题呢?因为背包问题是不讲物品的顺序的问题的。我们选两个元素,让A先发生与B后发生 和 B先发生A后发生的情况进行比较,然后就可以获得某种排序方式。最后发现c/b越小,最先发生更优。所以我们先排个序,在01背包就可以了。
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long int
const int maxn=1e5+10;
ll dp[maxn];
struct Node{
int a,b,c;
bool operator<(const Node x)const{
return (double)this->c/(double)this->b<(double)x.c/(double)x.b;
}
}node[55];
int main()
{
int t,n;
scanf("%d%d",&t,&n);
for(int i=1;i<=t;i++) dp[i]=-inf;
for(int i=1;i<=n;i++) scanf("%d",&node[i].a);
for(int i=1;i<=n;i++) scanf("%d",&node[i].b);
for(int i=1;i<=n;i++) scanf("%d",&node[i].c);
sort(node+1,node+1+n);
dp[0]=0;
for(int i=1;i<=n;i++){
int a=node[i].a,b=node[i].b,c=node[i].c;
for(int j=t;j>=c;j--){
dp[j]=max(dp[j],dp[j-c]+(ll)a-(ll)j*b);
}
}
ll Max=-inf;
for(int i=1;i<=t;i++) Max=max(Max,dp[i]);
if(Max<0) Max=0;
printf("%lld",Max);
return 0;
}