一、算法思路
与国王游戏的贪心策略相似, 我们先分析每头牛的危险值 = 他前面牛的(w)(重量值)和 - 自身的(s)(强壮值),要使每头牛的危险值最小,这显然是与(w) 和 (s)同时相关,所以先 (yy) 出一种作法按每头牛的(w + s)进行升序排序(题见多了可能就会有这种题感)。
数学分析:
牛 | 交换前 | 交换后 |
---|---|---|
(i) | $$sum_{j=1}^{i-1}w_j-s_i$$ | $$sum_{j=1}^{i-1}w_j+w_{i+1}-s_i$$ |
(i+1) | $$sum_{j=1}^{i}w_j-s_{i+1}$$ | $$sum_{j=1}^{i-1}w_j-s_{i+1}$$ |
其他牛的危险值显然不变,所以分析交换前后这两头牛中最大的危险值即可。
将上述式子进行化简,每个式子减去$$sum_{j=1}^{i-1}w_j$$得到如下式子
牛 | 交换前 | 交换后 |
---|---|---|
(i) | (-s_i) | (w_{i+1}-s_i) |
(i+1) | (w_{i}-s_{i+1}) | (-s_{i+1}) |
(ecause) (s,w)都是正数
( herefore) (w_i-s_{i+1}>-s_{i+1},w_{i+1}-s_i>-s_i)
所以,交换前后的最大值,就是在比较 (w_i-s_{i+1},w_{i+1}-s_i):
当(w_i-s_{i+1}>=w_{i+1}-s_i),即(w_i+s_i>=w_{i+1}+s_{i+1})时,交换后更优。
当(w_i-s_{i+1}<w_{i+1}-s_i),即(w_i+s_i<w_{i+1}+s_{i+1})时,交换前更优。
作法: 按每头牛的 (w + s) 进行排序, 当存在逆序时就进行交换(即升序排序),然后根据题意算出每头牛的危险值记录其中的最大值即可。
二、完整代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 50010;
PII cow[N];
int n;
int main() {
//优化输入
ios::sync_with_stdio(false);
cin >> n; //奶牛的数量
for (int i = 0; i < n; i++) {
int s, w; //牛的重量和强壮程度
cin >> w >> s;
cow[i] = {w + s, w}; //之所以这样记录数据,是因为我们找到贪心的公式,按 wi+si排序
}
//排序
sort(cow, cow + n);
//最大风险值
int res = -INF, sum = 0;
for (int i = 0; i < n; i++) {
int s = cow[i].first - cow[i].second, w = cow[i].second;
res = max(res, sum - s); //res为最大风险值
sum += w; //sum=w1+w2+w3+...+wi
}
printf("%d
", res);
return 0;
}