由于本题的做题选择会影响最后的得分,所以需要知道每一道题的优先级
下面我们来推导一下,如何来选择做题顺序,即每一道题的优先级
对于两道题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;


}