1023 美味菜肴 贪心 背包

链接:https://ac.nowcoder.com/acm/contest/24213/1023
来源:牛客网

题目描述

小明是个大厨,早上起来他开始一天的工作。他所在的餐厅每天早上都会买好 nnn 件食材(每种食材的数量可以视为无限),小明从到达餐厅开始就连续工作 TTT 时间。每道菜肴的制作需要特定的一种食材以及一段时间,但是食材一旦放久就不新鲜了,菜的美味值会降低。第 iii 道菜肴有三个属性 ai,bi,cia_i,b_i,c_iaibiciaia_iai 是该菜肴的美味值,bib_ibi是该菜肴所选食材不新鲜的速率,如果在第 ttt 时刻完成第 iii 道菜则美味值为:ai−t∗bia_i-t*b_iaitbi,完成这道菜需要 cic_ici 的时间。小明希望在这 TTT 时间内能做出菜肴使得总美味值最大,所以小明求助于你。


输入描述:

第1行输入三个整数 n,m,Tn,m,TnmT ,分别代表食材种类,菜肴种类和工作时间。
第2行输入 nnn 个整数 bib_ibi,代表第 iii 个食材不新鲜的速率。
接下来的m行,每行输入三个整数j,ai,cij,a_i,c_ijaici,分别代表第 iii 道菜肴需要的食材编号,菜肴的美味值,完成时间。
数据保证:0<n,m≤50,0<j≤n0<n,m≤50,0<j≤n0<n,m500<jn,其他值均<106<10^6<106,美味值必须通过完整做出菜肴得到,数据保证在规定时间内至少能完整做出1道菜肴。

输出描述:

输出一行,一个整数,表示最大总美味值。
示例1

输入

复制
1 1 74
2
1 502 47

输出

复制
408
示例2

输入

复制
2 2 10
2 1
1 100 8
2 50 3

输出

复制
84

备注:

最大总美味值可能为负。

分析

正如其名,这道题真是一道美味菜肴。

一般的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;
}

/*样例区


*/

//------------------------------------------------------------

posted @ 2022-07-07 21:22  er007  阅读(47)  评论(0编辑  收藏  举报