题目描述
小明是学校里的一名老师,他带的班级共有 n 名同学,第 i 名同学力量值为 ai。在闲暇之余,小明决定在班级里组织一场拔河比赛。
为了保证比赛的双方实力尽可能相近,需要在这 n 名同学中挑选出两个队伍,队伍内的同学编号连续:{aL1, aL1+1, …, aR1−1, aR1} 和 {aL2, aL2+1, …, aR2−1, aR2},其中 L1 ≤ R1 < L2 ≤ R2。
两个队伍的人数不必相同,但是需要让队伍内的同学们的力量值之和尽可能相近。请计算出力量值之和差距最小的挑选队伍的方式。
输入格式
输入共两行。
第一行为一个正整数 n。
第二行为 n 个正整数 ai。
输出格式
输出共一行,一个非负整数,表示两个队伍力量值之和的最小差距。
样例输入
5
10 9 8 12 14
样例输出
1
提示
【样例说明】
其中一种最优选择方式 :
队伍 1:{a1, a2, a3},队伍 2:{a4, a5},
力量值和分别为 10 + 9 + 8 = 27,12 + 14 = 26,
差距为 |27 − 26| = 1。
【评测用例规模与约定】
对于 20% 的评测用例,保证 n ≤ 50。
对于 100% 的评测用例,保证 n ≤ 103,ai ≤ 109。
暴力
分析
枚举所有队伍可能的值,排序后最小的 两相邻队伍的差值 即为结果
推测
区间是否重叠不影响结果
即
任意两区间和的差值为两区间不重叠部分和的差值
证明
对于两区间和A,B,其重叠部分和为S
两区间去除重叠部分和为
(A-S)-(B-S) = A-S-B+S = A-B
注意
最长队伍力量和可达10¹²,会爆int,所以开long long
用前缀和存储队伍力量和更优,但数据量过小,无所谓
C++ 代码
#include <bits/stdc++.h>
using namespace std;
long long a[1000];
vector<long long> s;
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
// 枚举i,j区间的力量和
for (int i = 0; i < n; i++)
{
long long t = 0;
for (int j = i; j < n; j++)
{
t += a[j];
s.push_back(t);
}
}
//若两数的差最小,其排序后一定相邻
sort(s.begin(), s.end());
long long ans = 1e9;
//找到最小的力量差
for (int i = 1; i < s.size(); i++)
{
ans = min(ans, s[i] - s[i - 1]);
}
cout << ans;
return 0;
}