题目来源:
题目描述:
小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。
输入描述:
输入包括两行,第一行一个整数n(1 ≤ n ≤ 50),表示学生的人数 第二行为n个整数h[i](1 ≤ h[i] ≤ 1000),表示每个学生的身高
输出描述:
输出一个整数,表示n个学生列队可以获得的最大的疯狂值。 如样例所示: 当队列排列顺序是: 25-10-40-5-25, 身高差绝对值的总和为15+30+35+20=100。 这是最大的疯狂值了。
输入例子1:
5 5 10 25 40 25
输出例子1:
100
解析:
规律题,首先对数组从小到大排序。例如:
1、先排最大值。
2、然后在最大的两端分别插入当前最小的两个值,小的向后插入,大的向前插入。
3、然后在两端分别插入当前最大的两个值,大的向后插入,小的向前插入。
4、重复2、3,直至所有的数据全部插入。如下:
5、微调数据(对于相等元素较多的情况,如下)。
#include <iostream>
#include <deque>
#include <vector>
#include <algorithm>
using namespace std;
deque <int> q;//双端队列
int main()
{
int n, a;
vector <int> arr;
cin>>n;
for(int i = 0; i < n; ++i)
{
cin>>a;
arr.push_back(a);
}
sort(arr.begin(), arr.end());
q.push_back(arr[n-1]);
int j = n-2, num = 1;
int i = 0;
while(num < n)
{
if(num >= n)
break;
if(num < n)//两端分别插入当前最小的两个值,小的向后插入,大的向前插入
{
q.push_back(arr[i++]);
num++;
if(num >= n)
break;
q.push_front(arr[i++]);
num++;
}
if(num < n)//两端分别插入当前最大的两个值,大的向后插入,小的向前插入
{
q.push_back(arr[j--]);
num++;
if(num >= n)
break;
q.push_front(arr[j--]);
num++;
}
}
int sum = 0;
/**
original 10 10 10 20 20 50 50
---> 20 20 10 50 10 50 10 ===> 170
mv first to last position ---> 20 10 50 10 50 10 20 ===> 180
*/
if(abs(q[0] - q[1]) < abs(q[n-1] - q[0]))//对于相等的数很多的时候,会有上例情况出现,所以要调整一下
{
q.push_back(q.front());
q.pop_front();
}
for(int i = 1; i < n; ++i)
{
sum += abs(q[i] - q[i-1]);
}
cout<<sum<<endl;
return 0;
}