考试题目 篱笆

题目描述

小明要做一个篱笆,篱笆由N块高度不同的木条组成,我们定义它的好看程度为相邻的篱笆的高度差的绝对值之和。小明已经买好了木条,但它不知道要如何安排顺序,才能使他的篱笆与小华的相似,并且尽量好看。

我们认为两个篱笆相似当且仅当两个篱笆的高低变化情况一致。即如果一个篱笆中的第i块木条高于第i+1块,则另一个篱笆中的第i块也高于第i+1块,则认为它们相似。

给出小华的篱笆信息,和小明买到的每块木板的长度,现在要求出小明的解决方案,使得他的篱笆与小华的相似,且尽量好看。如果有多种解决方案,任意输出一种即可。

输入

第一行一个整数N(2<=N<=300000),表示木条的数量。

第二行是N个不同的正整数,表示小华的篱笆。

第三行N个不同的正整数,表示小明的木板。

输出

第一行:一个整数,表示篱笆的好看程度。

第二行是N个不同的正整数,表示小明的篱笆。

样例输入

4
5 7 4 9
1 2 3 4

样例输出

7
2 4 1 3

考试时被吓到了,好恐怖的题,打了题目的表,马上换下一题,结果全Wa  /(ㄒoㄒ)/~~

老师评讲后,才明白了,这是一道贪心的题目,就样例数据来看,可以先把小华的篱笆画出来


这…………有美感吗?

言归正传

首先,我们来砍一下美感值是如何计算的,为两栅栏的绝对值,这时可以发现,一组栅栏的美感值只取决于起伏的顶端和底端,与中间的没有关系,于是,我们把栅栏看做一条山脉,看它的山脉走向(打开方式好像不对,怎么扯到地理了)…………看它的峰顶和山谷,用int数组来记录,除两边末端的栅栏外,其他都要使用两次(左边和右边),所以峰顶越高,山谷越低,美感值就越高,

于是将小明的木板从小到大排序,越高的放山峰,越低的放山谷,两端再凭其走向放置,再计算其美感值,剩下的木板凭走向放置,一一输出,KO!


实在不懂,丢代码了:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[300005],v[300005],e[300005],b[300005];
int n,s;
void scan()
{
    int i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&b[i]);
    for(i=2;i<n;i++)
    {
        if(b[i]>b[i-1]&&b[i]>=b[i+1])v[i]=2;//峰顶
        if(b[i]<b[i-1]&&b[i]<=b[i+1])v[i]=-2;//山谷
    }
    if(b[1]<b[2])v[1]=-1;//看两端
    else v[1]=1;
    if(b[n]<b[n-1])v[n]=-1;
    else v[n]=1;
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1);//给小明的木板排序
}
void work()
{
    int i,l=1,r=n;
    for(i=2;i<n;i++)
    {
        if(v[i]==2)e[i]=a[r--],s+=2*e[i];//峰顶取最大
        if(v[i]==-2)e[i]=a[l++],s-=2*e[i];//山谷取最小
    }
    if(v[1]==1)e[1]=a[r--],s+=e[1];//再考虑两端
    else e[1]=a[l++],s-=e[1];
    if(v[n]==1)e[n]=a[r--],s+=e[n];
    else e[n]=a[l++],s-=e[n];
    for(i=2;i<n;i++)//填中间的木板
        if(!v[i])
        {
            if(b[i-1]<b[i]) e[i]=a[l++];//看走向
            else e[i]=a[r--];
        }
}
int main()
{
    int i;
    scan();
    work();
    printf("%d
",s);
    int f=0;
    for(i=1;i<=n;i++)
    {
        if(!f)f=1;
        else printf(" ");//好习惯,行末无空格~(≧▽≦)/~
        printf("%d",e[i]);
    }
}
原文地址:https://www.cnblogs.com/Darknesses/p/12002563.html