这题貌似写过= - =...
我们考虑取每个的价值,假设说我们取了第i个,其他个没有取.取第i个,其他不选,对于在取i的时间内是一种什么情况呢?
假设我们有两种选择,第一个时间是ti.另外一个时间是tj.第一个每分钟减少w[i],另外一个减少w[j].第一个完成的价值是val[i],另外一个完成的价值是val[j].考虑取这两个的先后顺序,似乎很简单分析,因为我们所用时间相同,那么其他产生的代价是一样的,我们可以不予考虑.假如说我先取i再取j,那么我获得的价值是val[i]+val[j]-(ti+tj)w[j]-tiw[i].
同理考虑先取j再取i就是val[j]+val[i]-(tj+ti)w[i]-tjw[j].
如此,我们就会发现其实就是和w[],t有关系,我们肯定会优先选取最优的然后再去填背包,如此我们就可以用01背包解决.上面式子把同类项消除得到就是相邻两项w[]和t[]的积,假如小就说明收益高.如此就可以很轻松的解决这题了.
代码如下:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=55,M=100005; struct vv{ ll val,w,t;//分数 随时间减少的分数 时间 }a[N]; ll f[M];//背包. bool cmp(vv x,vv y) { return x.t*y.w<y.t*x.w; } int main() { int n,T; //输入 scanf("%d%d",&n,&T); for(int i=1;i<=n;i++) scanf("%lld",&a[i].val); for(int i=1;i<=n;i++) scanf("%lld",&a[i].w); for(int i=1;i<=n;i++) scanf("%lld",&a[i].t); //排序 sort(a+1,a+1+n,cmp); //背包容量是T,要求装的价值最高. for(int i=1;i<=n;i++) { for(int j=T;j>=a[i].t;j--) { f[j]=max(f[j],f[j-a[i].t]+a[i].val-j*a[i].w); } } ll ans=0; for(int i=T;i>=0;i--) ans=max(ans,f[i]); cout<<ans<<endl; return 0; }