再次见到这些排序的证明过程!
设有两件食材为\(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;
}
原文:https://www.cnblogs.com/Garen-Wang/p/10349182.html