【POJ 3045】Cow Acrobats(贪心)

tech2022-08-16  136

题面:Cow Acrobats

题目大意

相当于有 n n n 头奶牛在叠罗汉。每头牛都有两个特质,一个是重量 w w w,一个是强壮度 s s s。 每头牛都有一个崩溃风险,该风险等于在她上面的所有奶牛的总重量减去她本身的强壮度。所以每头牛都要找到合适自己的位置。 求:确定所有奶牛的位置,从而使任何奶牛中的最大风险最小。

思路

芜湖~~先贪心试一下。 将每头牛按照 w + s w+s w+s 从小到大排序,这样就得到正确的答案啦哈哈哈哈哈哈。

贪心证明:

设最优解为 r e a l _ a n s real\_ans real_ans,自己方案的解为 a n s ans ans

要证: a n s = r e a l _ a n s ans=real\_ans ans=real_ans 只需证:

a n s ≤ r e a l _ a n s ans\leq real\_ans ansreal_ans a n s ≥ r e a l _ a n s ans\ge real\_ans ansreal_ans

证明如下:

1、由题意可知,必然有 r e a l _ a n s ≤ a n s real\_ans\leq ans real_ansans

2、假设最优解不是按我们的算法来做的,则至少有一对牛是交换了位置的。已知第 k k k 头牛的特征为 ( w k , s k ) (w_k,s_k) (wk,sk),第 k + 1 k+1 k+1 头牛的特征为 ( w k + 1 , s k + 1 ) (w_{k+1},s_{k+1}) (wk+1,sk+1),且她们的风险分别为, r i s k , r i s k + 1 ris_k,ris_{k+1} risk,risk+1,则:

位置交换前交换后 k k k r i s k = ∑ i = 1 k − 1 w i − s k ris_k=\sum_{i=1}^{k-1}w_i-s_k risk=i=1k1wisk r i s k = ∑ i = 1 k − 1 w i + w k + 1 − s k ris_k=\sum_{i=1}^{k-1}w_i+w_{k+1}-s_k risk=i=1k1wi+wk+1skk+1 r i s k + 1 = ∑ i = 1 k w i − s k + 1 ris_{k+1}=\sum_{i=1}^kw_i-s_{k+1} risk+1=i=1kwisk+1 r i s k + 1 = ∑ i = 1 k − 1 w i − s k + 1 ris_{k+1}=\sum_{i=1}^{k-1}w_i-s_{k+1} risk+1=i=1k1wisk+1

同时减去 ∑ i = 1 k − 1 w i \sum_{i=1}^{k-1}w_i i=1k1wi 可得:

位置交换前交换后 k k k − s k -s_k sk w k + 1 − s k w_{k+1}-s_k wk+1sk k + 1 k+1 k+1 w k − s k + 1 w_k-s_{k+1} wksk+1 − s k + 1 -s_{k+1} sk+1

由于 s , w ≥ 1 s,w\ge1 s,w1,所以有: w k + 1 − s k > − s k w_{k+1}-s_k>-s_k wk+1sk>sk, w k − s k + 1 > − s k + 1 w_{k}-s_{k+1}>-s_{k+1} wksk+1>sk+1

所以,我们只要比较 w k + 1 − s k w_{k+1}-s_k wk+1sk w k − s k + 1 w_k-s_{k+1} wksk+1 的大小关系即可。 两边同时加上 s k + s k + 1 s_k+s_{k+1} sk+sk+1 得: w k + 1 + s k + 1 w_{k+1}+s_{k+1} wk+1+sk+1 w k + s k w_k+s_k wk+sk。 因为我们的贪心算法是按照 w + s w+s w+s 从小到大排序的。 所以, w k + 1 + s k + 1 ≥ w k + s k w_{k+1}+s_{k+1}\ge w_k+s_k wk+1+sk+1wk+sk。 所以,交换前的解要小于交换后的解,即 a n s ≤ r e a l _ a n s ans\leq real\_ans ansreal_ans

综上, a n s = r e a l _ a n s ans=real\_ans ans=real_ans。证毕。

代码

#include <bits/stdc++.h> #define sc scanf #define pf printf using namespace std; const int N = 5e4 + 10; const int INF = 0x3f3f3f3f; struct Node { int w, s; bool operator<(const Node &x) const { return w + s < x.w + x.s; } }cow[N]; int main() { int n; sc("%d", &n); for(int i = 0; i < n; i++) { int w, s; sc("%d %d", &w, &s); cow[i] = {w, s}; } sort(cow, cow + n); int ans = -INF, sum = 0; for(int i = 0; i < n; i++) { ans = max(ans, sum - cow[i].s); sum += cow[i].w; } pf("%d\n", ans); return 0; }
最新回复(0)