P1417烹调方案——背包问题中的排序

题目: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;
}

  

原文地址:https://www.cnblogs.com/Zinn/p/8391768.html