题目描述
小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,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
输出
复制100
思路:由中间向两边扩展,每次扩展都使得绝对值和最大(中间先最高,然后两边最低,然后两边最高)
#include<iostream> #include<algorithm> #include<cmath> #include<deque> using namespace std; int Max(int a,int b){ if(a>b){ return a; }else{ return b; } } int main(){ int n; int h[55]; cin>>n; for(int i=0;i<n;i++){ cin>>h[i]; } sort(h,h+n); deque<int> d; d.push_back(h[n-1]); int i=0,j=n-2; int f1=0; while(i<=j){ //由中间向两边扩展,每次向两边插入绝对值最大的, //但是当某边插入后导致绝对值为0时(最坏的情况),暂缓插入,f1++,当两边都无插入动作持续4次时,再插入 //f1的存在 使得 可以在情况不理想的时候,只先插入一边,等待下一轮的两边扩展(看看此时插入另一边会不会更好) int k = Max(abs(h[i]-d.front()),abs(h[j]-d.front())); if(k == abs(h[i]-d.front())){ if(k == 0 && f1<4){ f1++; continue; } f1 = 0; d.push_front(h[i]); i++; }else{ if(k == 0 && f1<4){ f1++; continue; } f1 = 0; d.push_front(h[j]); j--; } if(i>j){ //中途不退出来,会导致多算一次 break; } k = Max(abs(h[i]-d.back()),abs(h[j]-d.back())); if(k == abs(h[i]-d.back())){ if(k == 0 && f1<4){ f1++; continue; } f1 = 0; d.push_back(h[i]); i++; }else{ if(k == 0 && f1<4){ f1++; continue; } f1 = 0; d.push_back(h[j]); j--; } } deque<int>::iterator it; int front; int sum=0; for(it=d.begin();it!=d.end();it++){ if(it!=d.begin()){ sum += abs(front-*it); front = *it; }else{ front = *it; } //cout<<*it<<" "<<sum<<endl;; } cout<<sum; }