P1417 烹调方案 [贪心][dp]

P1417 烹调方案

再次见到这些排序的证明过程!

设有两件食材为\(1\)\(2\),三个属性分别为\(a_1,b_1,c_1\)\(a_2,b_2,c_2\),先完成的时间是\(t\)

第一种策略:先\(1\)\(2\)。美味指数为\(a_1 - t \times b_1 + a_2 - (t + c_1) \times b_2\)

第二种策略:先\(2\)\(1\)。美味指数为\(a_2 - t \times b_2 + a_1 - (t + c_2) \times b_1\)

令前者小于后者,那么:\(c_1 \times b_2 > c_2 \times b_1\)

意思就是说:自己的\(c\)与别人的\(b\)的乘积越小,那么优先级越大(因为\(t\)浪费得越少)。

所以按照这个从小到大排序,最后跑跑背包即可。

代码:

#include<bits/stdc++.h>
#define ll long long
const ll maxn = 200005;
struct Nodes {
    ll a, b, c;
} s[105];
ll dp[maxn];
ll t, n;
bool cmp(Nodes A, Nodes B) {
    return A.c * B.b < B.c * A.b;
}
int main() {
    scanf("%lld%lld", &t, &n);
    for(int i = 1; i <= n; i++) {
        scanf("%lld", &s[i].a);
    }
    for(int i = 1; i <= n; i++) {
        scanf("%lld", &s[i].b);
    }
    for(int i = 1; i <= n; i++) {
        scanf("%lld", &s[i].c);
    }
    std::sort(s + 1, s + n + 1, cmp);
    for(int i = 1; i <= n; i++) {
        for(ll j = t; j >= s[i].c; j--) {
            dp[j] = std::max(dp[j], dp[j - s[i].c] + s[i].a - j * s[i].b);
        }
    }
    ll ans = -0x3f3f3f3f3f3f3f3f;
    for(int i = 0; i <= t; i++) ans = std::max(ans, dp[i]);
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Garen-Wang/p/10349182.html