题目:https://www.luogu.org/problemnew/show/P1417
与普通的01背包不同的一点是加入物品的顺序对结果有影响,这里可以考虑贪心的想法,把对全局影响最小的物品排在前面;
排序不仅要考虑每件物品自身的时间大小,还要考虑对后面计算时的影响;
可以先从只有两个物品排序考虑,若有x和y,分两种情况:
1.x排在y前面:价值总和=(x.a-x.b*x.c)+(y.a-y.b*y.c-y.b*x.c);
2.y排在x前面:价值总和=(y.a-y.b*y.c)+(x.a-x.b*x.c-x.b*y.c);
可以看到唯一的不同就是减去(y.b*x.c)还是(x.b*y.c);
所以排序基准为:y.b*x.c<y.c*x.b;
代码如下:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int t,n; long long f[100005],mx; struct N{ long long a,b,c; }m[55]; bool cmp(N x,N y) { return y.b*x.c<y.c*x.b; } int main() { scanf("%d%d",&t,&n); for(int i=1;i<=n;i++) scanf("%lld",&m[i].a); for(int i=1;i<=n;i++) scanf("%lld",&m[i].b); for(int i=1;i<=n;i++) scanf("%lld",&m[i].c); sort(m+1,m+n+1,cmp); for(int i=1;i<=n;i++) for(long long j=t;j>=0;j--) if(j>=m[i].c)//不是>! f[j]=max(f[j-m[i].c]+m[i].a-m[i].b*j,f[j]); for(long long i=0;i<=t;i++) if(f[i]>mx)mx=f[i]; printf("%lld",mx); return 0; }