由于本题的做题选择会影响最后的得分,所以需要知道每一道题的优先级
下面我们来推导一下,如何来选择做题顺序,即每一道题的优先级
对于两道题t1,t2来说,有两种做题顺序,如下图的C12,C21,我们定义P1为t1的每分钟减小的分数,T1为做题需要的时间
两道题的初始总分数为sum(最大分数之和)
则
得分C12=sum-T1*P1-(T1+T2)*P2;
得分C12=sum-T2*P2-(T1+T2)*P1;
则 C12-C21=T2*P1-T1*P2
要判断两道题的大小,这上式同时除T1*T2的P1/T1-P2/T2 这样我们就发现了优先级函数为P/T即每分钟减小分数除需要的做题时间
排好序之后,进行01背包的dp算法
代码如下
#include<bits/stdc++.h> typedef long long ll; using namespace std; int N,T; const int maxn=55; const int maxt=1e5+5; ll dp[maxt]; struct node { int ma;//最大分数 int pm;//每分钟减小的分数 int re;//需要的时间 bool operator <(const node& rhs) const{ return pm*1.0/re > rhs.pm*1.0/rhs.re; } }nc[maxn]; int main() { cin>>N>>T; for(int i=0;i<N;i++) cin>>nc[i].ma; for(int i=0;i<N;i++) cin>>nc[i].pm; for(int i=0;i<N;i++) cin>>nc[i].re; sort(nc,nc+N); ll ans=0; for(int i=0;i<N;i++){ for(int j=T;j>=nc[i].re;j--){ dp[j]=max(dp[j],dp[j-nc[i].re]+nc[i].ma-nc[i].pm*j); ans=max(dp[j],ans); } } cout<<ans<<endl; }