题目链接: http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1899
Description
985有2 * n - 1个整数,他每次可以将其中n个数变号,操作次数不限,问他可以得到的最大和。
Input
第一行输入一个整数t,代表有t组测试数据。
每组数据占两行,第一行输入一个整数n,下面一行输入2*n-1个整数a[]。
注:1 <= t <= 32,1 <= n <= 1e3,-1e3 <= a[] <= 1e3。
Output
输出一个整数代表可以得到的最大和。
Sample Input
2
2
1 1 1
2
-10 20 -10
Sample Output
3 40
HINT
Source
有点小可怕,貌似从比赛到此刻的前一分钟一直就把题意理解错了,甚至感觉自己就像没读题一样,所以看题解看半天也没明白,可怕死了,不过现在明白了~
analyse:
对于给的每一组数据,我们记录里面负数的个数cnt,和绝对值之和sum,和绝对值最小的数minn.
1>首先我想说的是他每次可以将其中任意的n个数变号(我一直认为是固定的n个数),而且操作次数不限。
2>如果n是奇数的话,你可以使用各种手段将这2*n-1数都变成正数,不信的话,自己可以动手画画。
3> 如果n为偶数,那么我们只能改变偶数个数,那么就判断负数的个数是奇数还是偶数,如果是偶数,那么也可以全部变成正数;
如果是奇数,那么总有一个数不能变成正数,那么我们为了得到最优解(最大和),就让绝对值最小的为负数,sum- 2*minn(因为sum已经里面加了一次minn,所以要减去两倍的)即可。
#include <cstdio> #include <cstring> #include<iostream> #include<queue> #include<stack> #include<cmath> #include <map> #include <algorithm> using namespace std; const int maxn=1100; const int INF=0x3f3f3f3f; int main() { int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); int num, sum=0, cnt=0, minn=INF; for(int i=0; i<2*n-1; i++) { scanf("%d", &num); sum+=abs(num); minn=min(minn, abs(num)); if(num<0) cnt++; } if(n & 1) printf("%d ", sum); else { if(cnt & 1) sum-=2*minn; printf("%d ", sum); } } return 0; }