前言:毕竟是信息竞赛的题,题的难度系数极大。
题目描述
有一个长度为n的实数数组a,可以进行任意轮的操作,每轮选择一个i(0 < i < n-1)操作为a[i] = a[i+1] + a[i-1] - a[i],问最终a[0]+a[1]+…+a[n-1]最大可以是多少?
题目求解
创建一个a的差分数据b,有b[i] = a[i] - a[i-1]。则对a数组的操作相当于b数组的交换b[i]和b[i+1],当b[i+1]大于b[i]时,交换b[i]和b[i+1]相当于a[i]变大;当b[i+1]小于b[i]时,交换b[i]和b[i+1]相当于a[i]变小。故想让a数组和最大,即对b数组降序排序,还原得到a就可得到结果。
详细说明
- 开始b[i] = a[i] - a[i-1],b[i+1] = a[i+1] - a[i]。a数组进行一轮操作后,a[i-1],a[i],a[i+1]变为了a[i-1],a[i+1] + a[i-1] - a[i],a[i+1]。此时,b[i] = a[i+1] + a[i-1] - a[i] - a[i-1] = a[i+1] - a[i],b[i+1] = a[i+1] - (a[i+1] + a[i-1] - a[i]) = a[i] - a[i-1]相当于之前的b[i]和b[i+1]交换了位置。
- 而若b[i+1] > b[i],则有a[i+1] - a[i] > a[i] - a[i-1],相当于a[i+1] + a[i-1] - a[i] > a[i],即表示进行一轮操作后a[i]的值变大,即表示此时需要交换b[i]和b[i+1]。
参考代码
仅供参考
#include<stdio.h>
#include<stdlib.h>
//c语言调用快排,需要传的参数 ,表示想要升序还是降序
int cmp(const void *a, const void *b)
{
return *(int *)b - *(int *)a; //由大到小排序
}
#define len 10
int main(){
int a[len] = {23,12,5,23,45,18,9,81,29,53};
int b[len];
//得到a的差分数组b
b[0] = a[0];
for(int i = 1; i < len; ++i){
b[i] = a[i] - a[i-1];
}
qsort(b, 10, sizeof(int), cmp);//对差分数组降序排序
//还原数组a
for(int i = 1; i < len; ++i){
a[i] = b[i] + a[i-1];
}
//输出结果
int sum = 0;
for(int i = 0; i < len; ++i){
sum += a[i];
}
printf("%d",sum);
return 0;
}