题目简述:
给定一个数组,相邻两个之间可以随便相减,减数保留,被减数消失,最后这个数组只剩下一个数,求最后这个数的最大可能值。
贪心:
首先给定一系列数 x1,x2,x3,x4......xn。
我们考虑最后一次相减,必定是 x1,x2...... xi 得到的结果与 xi+1 .... xn 得到的结果,这两堆相减的结果,可以前者减去后者,也可以后者减去前者 ,但无论那种结果,所得的表达式中,一定有某个xk, 它的前面是 + , 也一定存在某个 xp, 它的前面是 - ,其他所有的数可以是 + ,也可以是 - ,但如果要结果最大,就要对这些数取绝对值。然后我们找到数组中一个最大的元素,它前面为 +, 找到一个数组中最小的元素,它的前面为 -,直接遍历即可。
也就是说,+x1+x2+........+xn 这样的序列是不可能的,-x1-x2....-xn也是不存在的.
例如我们考虑两个数,有一个 + ,有一个 -。
考虑三个数的时候,我们先把两个数看成一个整体 1 个 +, 1个-,然后第三个数作用时,可能是2个+ 1个-,也可能是2个- 1个 +。
然后我们用数学归纳法,假设 对 1,2,3......k 个数都成立,那么 k+1个数时,我们把这 k + 1个数 分为两堆,第一队 i 个,第二堆 j 个 (i 和 j 都大于1),第一堆可以产生(1,i-1),(2,i-2).....(i-1,1)对+-对(这里是根据数学归纳法),同理第二堆 (1,j-1),(2,j-2).....(j-1,1),这两堆自由组合就可以生成(1,k-1)......(k-1,1)对+-符号,(注意,(1,k-1)和(k-1,1)是有一堆为 1 时才产生的)。
证毕。(有点不严谨,欢迎读者指正)
AC Code:
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include <numeric>
int main() {
int N = 0;
cin >> N;
vector<int> a(N, 0);
int maxx = INT_MIN; int minn = INT_MAX;
for (int i = 0; i < N; i++) {
cin >> a[i];
maxx = max(maxx, a[i]);
minn = min(minn, a[i]);
}
// 至少一个 - ,至少一个 +
// 最小的那个数 - ,最大的那个数 +, 其他全部取绝对值
if (N == 1) {
cout << a[0]; return 0;
}
long long ans = maxx - minn;
int maxa = 0; int minb = 0;
for (int i = 0; i < N; i++) {
if (a[i] == maxx && maxa == 0) {
maxa = 1;
continue;
}
else if (a[i] == minn && minb == 0) {
minb = 1;
continue;
}
else {
ans += abs(a[i]);
}
}
cout << ans;
}