P1417 烹调方案

传送门

思路:

  可以用 01 背包做,但是如果直接套用 01背包 模板就 GG 了。因为随着时间的推移,每个物品的价值在不断的发生改变。

  现在考虑相邻的两个物品x,y。假设现在已经耗费 p 的时间,那么分别列出先做 x,y 的代价:

  ① a[ x ] - ( p + c[ x ] ) * b[ x ] + a[ y ] - ( p + c[ x ] + c[ y ] ) * by

  ② a[ y ] - ( p + c[ y ] ) * b[ y ] + a[ x ] - ( p + c[ y ] + c[ x ] ) * bx

  对这两个式子化简,得到 ①>② 的条件是 c[ x ] * b[ y ] < c[ y ] * b[ x ]。

  发现只要满足这个条件的物品对( x,y ),x 在 y 前的代价永远更优。

  因此可以根据这个条件进行排序,之后就是简单的01背包了。

                                     ——参考 kkksc03

标程:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<set>
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define maxn 51
typedef long long LL;
LL T,n,ans=-0x3f;
LL f[maxn][100001];
struct hh
{
    LL ai,bi,ci;
}t[maxn];
inline LL read()
{
    LL kr=1,xs=0;
    char ls;
    ls=getchar();
    while(!isdigit(ls))
    {
        if(!(ls^45))
            kr=-1;
        ls=getchar();
    }
    while(isdigit(ls))
    {
        xs=(xs<<1)+(xs<<3)+(ls^48);
        ls=getchar();
    }
    return xs*kr;
}
inline bool cmp(const hh&a,const hh&b)
{
    return a.ci*b.bi<b.ci*a.bi;
}
int main()
{
    T=read();n=read();
    for(LL i=1;i<=n;i++)
        t[i].ai=read();
    for(LL i=1;i<=n;i++)
        t[i].bi=read();
    for(LL i=1;i<=n;i++)
        t[i].ci=read();
    sort(t+1,t+n+1,cmp);
    for(LL i=1;i<=n;i++)
    {
        for(LL j=T;j>=0;j--)
        {
            if(t[i].ci<=j)
            {
                f[i][j]=max(f[i-1][j],f[i-1][j-t[i].ci]+t[i].ai-j*t[i].bi);
            }
            else f[i][j]=max(f[i][j],f[i-1][j]);
        }
    }
    for(LL i=1;i<=T;i++)
        ans=max(ans,f[n][i]);
    printf("%lld
",ans);
return 0;
}
原文地址:https://www.cnblogs.com/lck-lck/p/9800103.html