我好像忘记背包怎么写了。。写二维居然挂掉了。。改了一维才过。

题目大意:
题目解释起来比较复杂,直接贴原文链接:
https://ac.nowcoder.com/acm/problem/14704

思路:
看题目就给人浓浓的背包的感觉。
显然不可能直接背包。
我们假设最后已经得到了答案,那么我们必然会选择其中的一些菜肴,而且这些菜肴一定有固定的顺序去烹饪来使得美味值最大。
我们考虑最后答案是两种菜肴a1和a2。
最终答案有两种:ans1=a1-t1b1+a2-(t1+t2)b2 和 ans2=a2-t2b2+a1-(t1+t2)b1
要让选择顺序为a1,a2的话,我们需要令ans1>ans2
化简以后就是b1/t1 > b2/t2
那么我们只要先排序,然后问题就变成了某个菜肴选或不选的问题,就是01背包了。。

注意:
这里的一个问题是,答案可能为负数,所以我们令dp初始化为-inf,然后令dp[0]=0就可以了。
用二维数组会超内存,所以一维或者滚动数组优化一下。
代码:

#include<bits/stdc++.h>
using namespace std;
const long long inf=1e18;
int n,m,T;
long long dp[1000500];
int b1[55];
struct node{
    int x,a,c,b;
    double t;
}p[55];
bool cmp(node q,node w){
    return q.t>w.t; 
}
int main()
{
    cin>>n>>m>>T;
    for(int i=1;i<=n;i++)cin>>b1[i];
    for(int i=1;i<=m;i++){
        int j;
        cin>>j>>p[i].a>>p[i].c;
        p[i].b=b1[j];
        p[i].t=1.0*p[i].b/p[i].c;
    }
    sort(p+1,p+1+m,cmp);

        for(int j=0;j<=1000000;j++)dp[j]=-inf;

    dp[0]=0;
    for(int i=1;i<=m;i++){
        for(int j=T;j>=p[i].c;j--){
            dp[j]=max(dp[j],dp[j-p[i].c]+p[i].a-j*p[i].b);       
        }
    }
    long long ans=-inf;
    for(int i=1;i<=T;i++)ans=max(ans,dp[i]);
    cout<<ans<<endl;
    return 0;
}