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

京公网安备 11010502036488号