动态规划-codeforces
题目描述
牛牛正在打一场CF
比赛时间为T分钟,有N道题,可以在比赛时间内的任意时间提交代码
第i道题的分数为maxPoints[i],题目的分数随着比赛的进行,每分钟减少pointsPerMinute[i]
这是一场比较dark的Cf,分数可能减成负数
已知第i道题需要花费 requiredTime[i] 的时间解决
请问最多可以得到多少分
比赛时间为T分钟,有N道题,可以在比赛时间内的任意时间提交代码
第i道题的分数为maxPoints[i],题目的分数随着比赛的进行,每分钟减少pointsPerMinute[i]
这是一场比较dark的Cf,分数可能减成负数
已知第i道题需要花费 requiredTime[i] 的时间解决
请问最多可以得到多少分
输入描述:
第一行输入两个整数N,T (1 ≤ N ≤ 50, 1 ≤ T ≤ 100000)
第二行输入n个整数maxPoints[i]
第三行输入n个整数pointsPerMinute[i]
第四行输入n个整数requiredTime[i]
1 ≤ maxPoints[i],pointsPerMinute[i],requiredTime[i] ≤ 100000
输出描述:
输出一个整数
示例4
输出
复制97000
思路:首先,题目有分数和完成时间,两个属性。且有时间限制。可以得出是一个01背包问题。
但是由于题目的分数是在变化的,所以它不同于简单的背包问题。以此要算出它的性价比进行排序。先做能得分的且得分高的
假设分数为f,每分钟减少p,花费时间是t.有两个题目i,j.假设写题时间是t1+t2;
如果先写i题Ti=fi-pi*ti+fj-pj*(ti+tj)=fi+fj-pi*ti-pj*tj-pj*ti
如果先写j题Tj=fj-pj*tj+fi-pi*(ti+tj)=fi+fj-pi*ti-pj*tj-pi*tj
由Ti-Tj=pi*tj-pj*ti。所以。如果i题的性价比比j题的高,那么pi*tj>pj*ti
所以应当将性价比高的先写。所谓是同等时间内先拿分高的。
#include <cstdio> #include <cstdlib> #include <climits> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #include <iostream> using namespace std; typedef long long ll; const int mod = 1e9+7; const double PI=3.14159265358; const int INF=0x3f3f3f3f; struct node{ //分数 ll fen; //每分钟减少的分数 ll minfen; //花费的时间 ll time; //自定义排序方法 friend bool operator <(const node a,const node b){ return b.time*a.minfen>a.time*b.minfen; } }; node no[52]; //dp[i][j] i表示题数 j表示时间 ll dp[52][100010]; int t,n; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin>>n>>t; memset(dp,0,sizeof(dp)); memset(no,0,sizeof(no)); for(int i=1;i<=n;i++){ cin>>no[i].fen; } for(int i=1;i<=n;i++){ cin>>no[i].minfen; } for(int i=1;i<=n;i++){ cin>>no[i].time; } //排序。将性价比高的排在前面 sort(no+1,no+n+1); ll ans=0; //循环题数 for(int i=1;i<=n;i++){ //循环时间 for(int j=0;j<=t;j++){ //当前时间足够写完当前题目时 if(j>=no[i].time){ //等于当前时间内完成i-1题的分数与 //(当前时间-这一题的时)间内完成i-1的分数加上写完这一题的分数 //中的最大值 dp[i][j]=max(dp[i-1][j],dp[i-1][j-no[i].time]+no[i].fen-no[i].minfen*j); }else{ //此时时间不够完成此题时 //dp等于当前时间内完成i-1题的分数 dp[i][j]=dp[i-1][j]; } //答案等于这些方案中,分数最高的那个 ans=max(ans,dp[i][j]); } } cout<<ans<<endl; return 0; }