题目大意:给你n到题目,t分钟时间,没到题目初始分数为a,每分钟减小分数为b,做出来需要c分钟。问最多能得多少分。
思路:刚开始以为是01背包,背了半天发现背不动……还应该加个贪心的策略才可以。怎样贪心呢?就是说如果先做A题,那么被扣分数C1可以算出来。同理,先做B,那么被扣分数C2也可以算出来。如果C2 > C1,那么就先做A,因为这样在得分才能最大化。即做题顺序必定有个最优的。。接下来就是01背包的问题了。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
#define maxn 3005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 1000000000
struct node
{
int a , b , c;
}arr[maxn];
int dp[maxn];
bool cmp(node n1 , node n2)
{
return n1.b*n2.c > n2.b * n1.c;
}
int main()
{
int n , t , m;
scanf("%d" , &t);
while(t--)
{
mem(dp , 0);
scanf("%d %d" , &n , &m);
for(int i = 0 ; i < n ; i ++) scanf("%d %d %d" , &arr[i].a , &arr[i].b , &arr[i].c);
sort(arr , arr + n , cmp);
for(int i = 0 ; i < n ; i ++)
{
// cout << arr[i].a << endl;
for(int j = m ; j >= arr[i].c ; j --)
{
dp[j] = max(dp[j] , dp[j-arr[i].c] + arr[i].a- arr[i].b*j);
}
}
int ans = 0;
for(int i = 0 ; i <= m ; i ++)
{
ans = max(ans , dp[i]);
}
printf("%d\n" , ans);
}
return 0;
}