Codeforces 1107F(dp)

怎么就没人解释一下为啥用b排序可以保证正确性呢……太菜了,理解了好久。

时间流逝价值会丢失的背包,类似题洛谷1417

本题与洛谷1417不同之处在于流逝是有截止的。

1.这个dp[j]的含义是:最后跑路时欠了j个费所得到的最大钱数。

2.假设是不排序的,直接去背包,考虑两种转移,一种是选了当前这个以后到最后时欠的个数并不增多(即这个的k天都还了);另一种是这个也没还完。

3.如果直接都还了那顺序完全无所谓了,但是如果有这么几个都是最后要欠的,那么显然第一个要支付0天(即提钱当天就跑路了),第二个要支付1天,……第j个支付(j - 1)天。那么无论列一列式子(如洛谷1417)还是直观感受,反正就是这么几个,那肯定贪心地、尽量少扣大的b。这就是要按b从大到小排序的原因。

4.取dp[0~n]的最大值。

 1 const int maxn = 550;
 2 int n;
 3 struct off {
 4     ll a, b, k;
 5 
 6     bool operator < (const off &rhs) const {
 7         return b > rhs.b;
 8     }
 9 }offer[maxn];
10 ll dp[maxn];
11 
12 int main() {
13     cin >> n;
14     rep(i, 1, n)    cin >> offer[i].a >> offer[i].b >> offer[i].k;
15 
16     sort(offer + 1, offer + 1 + n);
17     rep(i, 1, n) {
18         irep(j, i, 0) {
19             dp[j] = max(dp[j], dp[j] + offer[i].a - offer[i].b * offer[i].k);
20             if (j)  dp[j] = max(dp[j], dp[j - 1] + offer[i].a - offer[i].b * (j - 1));
21         }
22     }
23 
24     cout << *max_element(dp, dp + n + 1) << endl;
25     return 0;
26 }
原文地址:https://www.cnblogs.com/AlphaWA/p/10657836.html