网易编程题 疯狂队列

来源:互联网 发布:淘宝u站怎么进入 编辑:程序博客网 时间:2024/06/05 23:35

小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,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 10 25 40 25 
输出
100
解析:根据示例数组 绝对值总和为15+30+35+20=100
其中我们排序为
a0->5          a1->10          a2->25          a3->25          a4->40
15=25-10=a2-a1
30=40-10=a4-a1
35=40-5=a4-a0
20=25-5=a3-a0
即:100=(a4*2 - a0*2) + (a3*2 - a1*2) + a2 - a3
其中,先找到最大值和最小值放在数组的首位和末尾,然后带入计算
a4为最大值,因为a4左右两次计算都是减数,故为+a4*2
a0为最小值,因为a0左右两次计算都是被减数,故为-a0*2
接着找剩下部分的最大值和最小值......放在次首位和次末尾.......同样计算两次
但是问题来了,到最后肯定有放在队列边上的元素,这样的话肯定有两个元素只能计算一次(无论是减数还是被减数)。
1。.如果队列长度n为偶数,max和min是成对出现的,最后一对max和min都多计算了一次,减去即可。
2。如果队列长度n是奇数,在找到最后一对max和min的时候,最中间值(mid)也会出现。我们先把mid去掉,就是一个偶数长度的队列
他的疯狂值(maxMad)和 上面的  1。一样,减去max和min。然后再把mid添加进去,添加到哪儿呢?
如果max-mid大于mid-min,则添加到max边上,这样就是maxMad = maxMad + max - mid
如果max-mid小于mid-min,则添加到min边上,这样就是maxMad  = maxMad + mid - min
如下:

#include <iostream>#include <string.h>using namespace std;int main(){int n, i, j;cin >> n;//cout << n;int h[n];for(i=0; i<n; i++){cin >> h[i];}int max, min, maxMad;maxMad = 0;for(i=0; i<n/2; i++){min = h[i]; max = h[n-i-1];for(j=i+1; j<n-i; j++){if(min>h[j]){//更小的就换过来,换到当前未排序部分的 队首h.imin=h[j]; h[j]=h[i]; h[i]=min;}if(max<h[j]){//更大的也换过来,换到当前未排序部分的 队尾h.n-i-1max=h[j]; h[j]=h[n-i-1]; h[n-i-1]=max;}}maxMad = maxMad + max*2 - min*2;}maxMad = maxMad - (max - min);//这最后一组max和min都多计算了一次,要减去if(n%2!=0){//如果队列长度是奇数,则把最中间的值(排序到for结束的当前h.i就是中间值)if((h[i]-min) > (max-h[i])){//means (h[i]-min) > (max-h[i])h[i]*2 > min + maxmaxMad = maxMad + (h[i] - min);//max Calculate once more, so cut it}else{//max+min >= h[i]*2 //means (h[i]-min) <= (max-h[i])maxMad = maxMad + (max - h[i]);}}cout << maxMad;return 0;}


/*********
如果需要输出具体队列的话就把第一组max.0放在中间,min.0放左边(其实无所谓的,如果放左边,则下面的max.1要放在max.0的左边(也就是min.0的左边)),
然后以后每一个max.i交替放在max.0的左右两侧(先放左还是先放右根据max.0和min.0的防止位置来定),
min.i也是同理放置.直到最后一组max和min以及可能有可能无的mid.
*********/

 
原创粉丝点击