这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!
一、题目大意
题目的大致意思就是,给定一个长度为n的不减数组,即后一个元素大于等于前一个元素,然后要求把这个数组分为k个非空连续子数组,定义每种切分的方法代价为这k个子数组最大值减最小值的和,用公式表示即:
其中,max(i)和min(i)分别表示第i个子数组中的最大值和最小值。求使代价最小的切分方法。
二、题目思路以及AC代码
本来这道题也想写水题的,但后来想想,都写水题之后也不好区分,就写成思维题了。
这题的关键就是找寻一种合理的切分方法。这里我提供一种思路,就以题目中的第一个样例为例。
输入的数组为4 8 15 16 23 42,那么由于要求差,我们不妨再开一个数组用于保存其相邻两个数的差,即diff数组,其内容是4 7 1 7 19,然后题目要求我们切分数组,那么切分完之后,会对结果有什么影响呢?比如我们现在在8和15中间切了一下,那么结果就是4+1+7+19,如果再在23和42之间切一刀,那结果就是4+1+7,可以发现,我们的切分无非是在去除diff中的某些值,那么结果要求和最小,那么也就是说,只要把diff中最大的k-1个值去除掉就好了(k-1的原因是要分成k组,则要切k-1刀)。
下面给出AC代码:
#include <iostream>
#include <algorithm>
#define MAXN 300010
using namespace std;
int n, k;
int a[MAXN];
int diff[MAXN];
bool cmp(int a, int b) {
return a > b;
}
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i < n; i++) {
diff[i] = a[i + 1] - a[i];
}
sort(diff + 1, diff + n, cmp);
int ans = 0;
for (int i = k; i < n; i++) {
ans += diff[i];
}
cout << ans << endl;
return 0;
}
如果有问题,欢迎大家指正!!!