题目链接:nyist747
解法:贪心 动态规划
思路:
如果没有 B[i]这个属性的话就是明显的 01 背包问题。
现在考虑相邻的两个物品 x,y.假设已经耗费 p 的时间,那么分别列出先做 x,y 的代价:
A[x]-(p+C[x])*B[x]+A[y]-(p+C[x]+C[y])*B[y] ①
A[y]-(p+C[y])*B[y]+A[x]-(p+C[y]+C[x])*B[x] ②
对这两个式子化简,得到 ①>② 的条件是 c[x]*b[y]<c[y]*b[x].
发现只要满足这个条件的物品对(x,y),x 在 y 前的代价永远更优。
因此可以根据这个条件进行排序,之后就是简单的 01 背包了。
这是赛后学长给的题解,比赛的时候我是用01背包写的,对花费的时间进行的排序,那时候是觉得话费时间少的应该优先做,交了以后直接WA了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
long long d[100005];
struct node
{
long long a,b,c;
}s[100];
bool cmp(node x,node y)
{
return x.c * y.b < x.b * y.c;
}
int main()
{
int T,n,i,j;
while(~scanf("%d%d",&T,&n))
{
for(i = 0; i < n; i ++)
scanf("%lld%lld%lld",&s[i].a,&s[i].b,&s[i].c);
memset(d,0,sizeof(d));
sort(s,s+n,cmp);
for(i = 0; i < n; i++)
{
for(j = T; j >= s[i].c ; j --)
{
d[j] = max(d[j],d[j-s[i].c]+s[i].a-j*s[i].b);
}
}
long long ans = 0;
for(i = 0; i <= T; i ++)
ans = max(ans,d[i]);
printf("%lld\n",ans);
}
return 0;
}