1023 美味菜肴 贪心 背包
链接:https://ac.nowcoder.com/acm/contest/24213/1023
来源:牛客网
题目描述
输入描述:
第2行输入 nnn 个整数 bib_ibi,代表第 iii 个食材不新鲜的速率。
接下来的m行,每行输入三个整数j,ai,cij,a_i,c_ij,ai,ci,分别代表第 iii 道菜肴需要的食材编号,菜肴的美味值,完成时间。
数据保证:0<n,m≤50,0<j≤n0<n,m≤50,0<j≤n0<n,m≤50,0<j≤n,其他值均<106<10^6<106,美味值必须通过完整做出菜肴得到,数据保证在规定时间内至少能完整做出1道菜肴。
输出描述:
输出一行,一个整数,表示最大总美味值。
备注:
最大总美味值可能为负。
分析
正如其名,这道题真是一道美味菜肴。
一般的01背包:有n件物品,m的空间,满足空间要求的情况下得到最大价值,元素和元素之间没有先后之分,变换次序没有关系
但这题对每个物品的价值加了一个时间限制,导致放进去的物品是先放进去还是后放进去有了分别。
参考耍杂技的牛。对于第j秒,和j + c[i+1] 秒
交换 两个食品 a[i],a[i+1]前:m1 = a[i] - (j + c[i] )* b[i] + a[i+1] - (j + c[i] + c[i+1]) * b[i+1]
交换 两个食品 a[i],a[i+1]后:m2 = a[i+1] - (j + c[i+1]) * b[i+1] + a[i] - (j + c[i+1] + c[i]) * b[i]
将两个式子的j 设为0,a[i] + a[i+1] 消掉得:
1. - c[i+1] * b[i+1] - c[i] * b[i] - c[i] * b[i+1]
2. - c[i] * b[i] - c[i+1] * b[i+1] - c[i+1] * b[i];
假设交换前更优,则1 > 2
- c[i] * b[i+1] > - c[i+1] * b[i];
c[i] / b[i] < c[i+1] / b[i+1]
所以,要使满意度最大,则c[i] / b[i] 最小,所以按照 c[i] / b[i] 从小到大排序就可以了
ps : 我是说或许:贪心问题就是次序问题。
//-------------------------代码----------------------------
#define int LL
const int N = 1e5+10;
int n,m,t;
struct node {
int a,b,c;
bool operator<(const node & w) const {
return c * w.b < b * w.c;
};
} a[N];
int tmp[N];
int f[N];
void solve()
{
cin>>n>>m>>t;
// V<V<int>>mp(n+1,V<int>(m+1));
fo(i,1,n) cin>>tmp[i];
fo(i,1,m) {
int x;
cin>>x>>a[i].a>>a[i].c;
a[i].b = tmp[x];
}
sort(a+1,a+1+m);
memset(f,-0x3f,sizeof f);
f[0] = 0;
fo(i,1,m) {
of(j,t,a[i].c) {
f[j] = max(f[j],f[j-a[i].c] + a[i].a - j * a[i].b);
}
}
LL ans = -1e16;
fo(i,1,t) {
ans = max(ans,f[i]);
}
cout<<ans<<endl;
rt;
}
signed main(){
clapping();TLE;
// int t;cin>>t;while(t -- )
solve();
// {solve(); }
return 0;
}
/*样例区
*/
//------------------------------------------------------------