题目描述:小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。 ( '-' )ノ)`-' )
通过题目描述我们可以采取双端队列来进行求解;【从队头队尾都可以进行插入删除操作】
思路:首先对数字进行排序,接下来把最大的数字先放进队列,之后在最大数字的两端分别放入最小的两个值,在最小两个值的左右两侧再放入最大的两个值,直到放完所有数字;But,当有单个数字剩余时,我们需要比较其和队头的差值和队尾的差值来比较究竟放在哪里值最大!
代码中完整实现了排列,但是也可以直接计算abs值;
#include <iostream>
#include<deque>
#include<algorithm>
using namespace std;
int main()
{
int n;
int x;
int res = 0;
cin>>n;
vector<int> v1;
int l = 0;
int r = n-1;
for(int i = 0;i < n;i++)
{
cin>>x;
v1.push_back(x);
}
sort(v1.begin(),v1.end()); //将所有数字进行排序
deque<int> v2; //选择双端队列对学生排序进行操作
v2.push_front(v1[r]); //先放入最大值
r--; //r此刻指向第2大的数字
while(l <= r)
{
if(l <= r)
{
v2.push_front(v1[l++]); //将最小值放入队头
v2.push_back(v1[l++]); //用两个最小的值把最大值包围
}
if(l <= r)
{
v2.push_front(v1[r--]);
v2.push_back(v1[r--]); //同理
}
}
if(abs(v2[n-1]-v2[n-2]) < (abs(v2[n-1]-v2[0])))
{
v2.push_front(v2.back()); //把最右边的值放在最左边
v2.pop_back(); //抛出最右边的值
}
for(int j = 1;j < n;j++)
{
res += abs(v2[j]-v2[j-1]);
}
cout << res;
return 0;
}
(∩•̀ω•́)⊃-*⋆代码参考:https://www.cnblogs.com/zdy1996/p/7587257.html