题意:类似cf的赛制,每道题目有A,B,C三个值,A表示初始分数,B表示每分钟题的分数会减少B,C表示做这道题需要C分钟,数据保证分数不会变为负数。现在给出比赛时长,问安排做题的顺序,求最大得分。
思路:这道题是一道非常经典的题。首先很容易想到一件事,给出的题哪个先做没有先后顺序,那么在动态规划的时候,必然有前后顺序,所以要么就是状态压缩,要么就是之前就把这些题目排序了,使得后面是有序的。状压不用考虑了因为数据太大,所以我们考虑要如何排序。
现在有A1,B1,C1和A2,B2,C2这两道题,如果先做1再做2的得分是A1-B1*C1+A2-B2*(C1+C2),如果先做2在做1的得分是A2-B2*C2+A1-B1*(C1+C2),令先做1再做2的得分更高些,那么有A1-B1*C1+A2-B2*(C1+C2) >= A2-B2*C2+A1-B1*(C1+C2),解得B1*C2>=B2*C1
所以,只要B1*C2>=B2*C1,那么先做题1再做题2的分数就会更高。
所以,我们只需要根据这个来排序,再做dp,就能得到答案了.
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<math.h> 7 #include<algorithm> 8 #include<queue> 9 #include<set> 10 #include<bitset> 11 #include<map> 12 #include<vector> 13 #include<stdlib.h> 14 #include <stack> 15 using namespace std; 16 #define PI acos(-1.0) 17 #define max(a,b) (a) > (b) ? (a) : (b) 18 #define min(a,b) (a) < (b) ? (a) : (b) 19 #define ll long long 20 #define eps 1e-10 21 #define MOD 1000000007 22 #define N 1006 23 #define M 5006 24 #define inf 1<<26 25 int n,m; 26 struct Node{ 27 int a,b,c; 28 bool operator <(const Node &x) const{ 29 return (ll)b*x.c>(ll)x.b*c; 30 } 31 }node[N]; 32 int dp[M]; 33 int main() 34 { 35 int t; 36 scanf("%d",&t); 37 while(t--){ 38 scanf("%d%d",&n,&m); 39 for(int i=1;i<=n;i++){ 40 scanf("%d%d%d",&node[i].a,&node[i].b,&node[i].c); 41 } 42 sort(node+1,node+n+1); 43 44 memset(dp,0,sizeof(dp)); 45 for(int i=1;i<=n;i++){ 46 for(int j=m;j>=node[i].c;j--){ 47 dp[j]=max(dp[j],dp[j-node[i].c]+(node[i].a-node[i].b*j)); 48 } 49 } 50 51 int ans=0; 52 for(int i=0;i<=m;i++){ 53 ans=max(ans,dp[i]); 54 } 55 printf("%d ",ans); 56 } 57 return 0; 58 }