1 题目
1.1 问题描述
有
- 选取任意一个数
,加上或减去 - 选取任意两个数
,其中一个加 ,另一个减
问题,最少操作多少次
- 所有的数变成
- 除了第一个数外,其它所有的数变成
2 输入样例
5
1 2 -4 -1 8
3 输出样例
11
4 数据范围
5 解析
分类讨论
1. 所有的数都是正数或负数
当所有的数都是正数时,显然只能挑一个数进行减
那最少的操作次数显然是:所有数的和的绝对值,用数学公式表示如下
2. 数有正有负
为了思考🤔复杂的问题,我们可以使用这种方法: 先简化问题的复杂度,例如缩小数量,使数据有序等,先考虑简单的问题,然后依次增加难度来寻找问题的规律, 这种方法我称为**++简化法++**
先考虑只有两数,一正一负的情况,例如
然后考虑有三个数,例如
我们发现:
- 只有正(负)数的时候,只用操作正(负)数,简单,答案只有正(负)数的数值与关.
- 当同时有正负数的时候,可以选一对正负数,同时操作,正减
,负加 .也就是说这种操作可以一值做直到只有正(负)时. - 正数只能加
,负数只能减
最后,可以想到,一般的情况下,有正有负.可以先固定一个正数不变,也就是每一次
我们把问题转化成一个新问题(化归法): 设,面对一个数字集合
显然
其实这种思想我称为:分解子问题.后面会重点讲这种思想
整个问题,可以形象化地等效成
- 每一个正数都对应一个红色的柱子,负数对应蓝色的柱子.
- 正数的加
,就等效成红色柱子消去一层.负数同理. - 把正数的数和负数对就的柱子磊起来,各磊成两个柱子,每一次的操作,就是同时消去两个柱子的一层,问最多操作多少次.
上面这种方法,我称为**++等效法++**,这是一种非常重要的思想.
显然最终答案为
用数学公式表达就是如下
6 代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int n;
int sp,sn; //正数与负数的和
int main() {
cin >> n;
for(int i = 1;i <= n ;++i) // i: 1->n
{
int t;
std::cin >> t;
if( t > 0)
sp += t;
else
sn += -t;
}
cout<< max(sp,sn);
return 0;
}
7 练习题目
8 相关题解
暂无相关题解