Solution:
一道很典型的dp题目,
对于 20% 的数据(Bi=0),直接使用01背包即可。
对于 100% 的数据,我们需要进行分析,当我们对 …a,b… 和 …b,a… (…表示的是相同的序列)进行求最大值时,我们只需对不同的序列(也就是a,b)的不同排列方式求最大值,当a消耗ta秒,每秒消耗x,b消耗tb秒,每秒消耗y时,我们得到这两种不同排列方式的不同消耗分别为 [ta*x+(ta+tb)*y]① 和 [tb*y+(ta+tb)*x]②. 对①②两式做差,得到 [ta*y-ta*x]③,令③<0得到ta*y<tb*x④;于是我们便以④为compare函数进行排序,再进行01背包求解即可。
1 #include<algorithm> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int maxm=3e3+5; 6 int f[maxm]; 7 struct cp{ 8 int s,x,t; 9 }e[maxm]; 10 bool cmp(cp a,cp b){return a.t*b.x<a.x*b.t;} 11 inline int max(int a,int b){return a>b?a:b;} 12 inline void init(){ 13 memset(e,0,sizeof e); 14 memset(f,0,sizeof f); 15 } 16 inline int read(){ 17 char ch=getchar(); 18 int x=0,f=1; 19 while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} 20 while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar(); 21 return x*f; 22 } 23 int main(){ 24 /* freopen("score.in","r",stdin); 25 freopen("score.out","w",stdout);*/ 26 int T=read(),n,t,ans=0; 27 while(T--){ 28 init(); 29 ans=0; 30 n=read(),t=read(); 31 for(int i=1;i<=n;i++) e[i].s=read(),e[i].x=read(),e[i].t=read(); 32 sort(e+1,e+n+1,cmp); 33 for(int i=1;i<=n;i++) 34 for(int j=t;j>=e[i].t;j--) 35 f[j]=max(f[j],f[j-e[i].t]+e[i].s-j*e[i].x); 36 for(int i=1;i<=t;i++) ans=max(ans,f[i]); 37 /* for(int i=1;i<=n;i++){ 38 for(int j=1;j<=t;j++) f[i][j]=f[i-1][j]; 39 for(int j=t;j>=e[i].t;j--) 40 f[i][j]=max(f[i-1][j],f[i-1][j-e[i].t]+e[i].s-e[i].x*j); 41 }*/ 42 for(int i=1;i<=t;i++) ans=max(ans,f[i]); 43 printf("%d ",ans); 44 } 45 return 0; 46 } 47 /* 48 1 49 4 10 50 110 5 9 51 30 2 1 52 80 4 8 53 50 3 2 54 Ans: 88 55 */