Jzoj4892 最优得分

给你n道题目,你有t的时间,每个题有一个初始的分数Ai,让后每过1分钟,第i道题目分值减少Bi

假设你可以做出全部题目,而做一个题i的用时是固定的常数Ci,那么请问你最多能得到多少分

(好刺激的赛制呢)

显然是一个dp,但是光dp还不够,我们还要套上贪心才能最优

考虑当前已经决定做哪几道题目,那么用什么顺序去完成这些题目得分最高?

我们随便考虑一个顺序X,考虑交换其中两个题目X[j]和X[j+1]

如果保持不变,那么损失C[x[i]]*B[x[i+1]]分,如果交换,则损失B[x[i]]*C[x[i+1]]分

比较两者大小,若C[x[i]]*B[x[i+1]]>B[x[i]]*C[x[i+1]]则应该交换两者

移项可得B[x[i]+1]/C[x[i]+1]>B[x[i]]/C[x[i]]

所以我们将所有的题目按照B[i]/C[i]从大到小排序

让后做类似于01背包问题的dp即可

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct Q{ int A,B,C; } s[1010];
int f[3010],n,m;
inline bool c1(Q a,Q b){ return a.C*b.B>b.C*a.B; }
int score(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d%d%d",&s[i].A,&s[i].B,&s[i].C);
	memset(f,0,3010<<2);
	sort(s+1,s+1+n,c1);
	for(int i=1;i<=n;++i)
		for(int j=m;j>=s[i].C;--j)
			f[j]=max(f[j],f[j-s[i].C]+s[i].A-(m-j+s[i].C)*s[i].B);
	printf("%d\n",f[m]);
}
int main(){
	freopen("score.in","r",stdin);
	freopen("score.out","w",stdout);
	int T; for(scanf("%d",&T);T--;score());
}


posted @ 2017-11-02 21:44  扩展的灰(Extended_Ash)  阅读(105)  评论(0编辑  收藏  举报