2018网易内推笔试编程题(二)

上一章限于篇幅,特来续篇,哈哈



7. 疯狂队列

小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。
输入描述:

输入包括两行,第一行一个整数n(1 ≤ n ≤ 50),表示学生的人数
第二行为n个整数h[i](1 ≤ h[i] ≤ 1000),表示每个学生的身高

输出描述:

输出一个整数,表示n个学生列队可以获得的最大的疯狂值。

如样例所示:
当队列排列顺序是: 25-10-40-5-25, 身高差绝对值的总和为15+30+35+20=100。
这是最大的疯狂值了。
解题思路:拿到这种题,首先把数学柿子弄出来,
假如存在身高序列:x1,x2,x3,x4,x5,x6,x7
那疯狂值即为sum = |x1 - x2| + |x2 - x3| + |x3 - x4| + |x4 - x5| + |x5 -x6| + |x6 - x7|
最大疯狂值sum(max) =求上式的最大值。
仔细观察上述柿子,我们可以发现x2~x6每个数参与计算了两次。x1和x7只计算了一次。那有什么用呢,仔细想一下,差最大,是不是尽量要让最大值与最小值做差。那这样的话,我们只需,把数列从小到大排个序,并从中间分为两队s1,s2,sum(s2)*2-sum(s1)*2,每个数参与两次计算,但是要注意,中间的两个数最为靠近,其差值也最小,只能参与一次计算,他们即上述柿子中的x1与x7。
序列长度为奇数的话,中间的数不参与计算(即使参与计算结果也为0),为偶数的话,中间的两个数只参与计算一次,即不用乘以2。
举个栗子:5 10 25 40 25
排序:5 10 25 25 40
分队s1:5 10
分队s2: 25 40
sum(s1)*2 = 30 ; sum(s2)*2=130
最大疯狂值:130-30 = 100
AC代码:

#include
#include
using namespace std;
int main(){

    int n;
    int a[55];
    while(scanf("%d",&n) != EOF)
    {
        for(int i=0; iscanf("%d",&a[i]);
        int sum1=0, sum2=0;
        sort(a,a+n);
        //分奇偶情况进行讨论
        if(n & 1){ //奇数,前半部分之和乘2,后半部门之后乘2
            for(int i=0; i2; i++)
                sum1 += a[i];
            sum1 *= 2;
            for(int i=(n+1)/2; i2;
        }
        else{
            for(int i=0; i2-1; i++)
                sum1 += a[i];
            sum1 *= 2; 
            //中间最近邻的两个数(a[n/2-1],a[n/2])只能参与一次计算,因此不需要乘以2
            sum1 += a[n/2-1];
            for(int i=n/2+1; i2;
            sum2 += a[n/2];

        }
        printf("%d\n",sum2-sum1);
    }
    return 0;
}

8. 小易喜欢的数列

小易非常喜欢拥有以下性质的数列:
1、数列的长度为n
2、数列中的每个数都在1到k之间(包括1和k)
3、对于位置相邻的两个数A和B(A在B前),都满足(A <= B)或(A mod B != 0)(满足其一即可)
例如,当n = 4, k = 7
那么{1,7,7,2},它的长度是4,所有数字也在1到7范围内,并且满足第三条性质,所以小易是喜欢这个数列的
但是小易不喜欢{4,4,4,2}这个数列。小易给出n和k,希望你能帮他求出有多少个是他会喜欢的数列。
输入描述:

输入包括两个整数n和k(1 ≤ n ≤ 10, 1 ≤ k ≤ 10^5)

输出描述:

输出一个整数,即满足要求的数列个数,因为答案可能很大,输出对1,000,000,007取模的结果。
解题思路:动态规划问题:设a[i][j]表示长度为i,并以j结尾的数列个数。
则状态转移方程为a[i][j] = a[i-1][1~k]
由于条件3:相邻的两个数AB要满足(A <= B)或(A mod B != 0),
(A mod B != 0)即可转化为后一个数不能是前一个数的约数,但A==B除外。
因此我们可以前两个条件,计算出所有的数列个数,在根据第三个条件,减去后一个数是前一个数的约数的情况
AC代码:

#include
using namespace std;
#define N 100000+5
#define Infi 1000000007
int a[15][N];
int main(){
    int n,k;
    while(cin>>n>>k){
        a[0][1]=1;
        for(int i=1;i<=n;i++){
            int num1=0;
            for(int j=1;j<=k;j++)
                num1 = (num1 + a[i-1][j]) % Infi;
            for(int j=1;j<=k;j++){
                int num2=0;
                for(int z=j+j; z<=k; z+=j)
                    num2 = (num2 + a[i-1][z]) % Infi;
                a[i][j]= (num1 - num2 + Infi) % Infi;
            }
        }
        int num=0;
        for(int i=1;i<=k;i++)
            num = (num + a[n][i])%Infi;
        cout<return 0;
}

6. 堆棋子

小易将n个棋子摆放在一张无限大的棋盘上。第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现有一个格子中至少有i(1 ≤ i ≤ n)个棋子所需要的最少操作次数.

输入描述:

输入包括三行,第一行一个整数n(1 ≤ n ≤ 50),表示棋子的个数
第二行为n个棋子的横坐标x[i](1 ≤ x[i] ≤ 10^9)
第三行为n个棋子的纵坐标y[i](1 ≤ y[i] ≤ 10^9)

输出描述:

输出n个整数,第i个表示棋盘上有一个格子至少有i个棋子所需要的操作数,以空格分割。行末无空格

如样例所示:
对于1个棋子: 不需要操作
对于2个棋子: 将前两个棋子放在(1, 1)中
对于3个棋子: 将前三个棋子放在(2, 1)中
对于4个棋子: 将所有棋子都放在(3, 1)中
示例1
输入

4
1 2 4 9
1 1 1 1
输出

0 1 3 10

解题思路:这题我没做出来,一开始是考虑把每个点到其余各个点的距离算出来,然后从小到大排序,计算前k个之和sum,并且每次都要更新 sum使其最小。但一直没有A掉,参考了别人的代码,发现X和Y是独立的,并且聚合点就在这些XY的组合中,但我证明不出来哇,尴尬。。。。。
AC代码:

#include
#include
using namespace std;
#define N 55
#define NN 0xfffffff
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        int x[N],y[N],dis[N*N];
        for(int i=0; iscanf("%d",x+i);
        for(int i=0; iscanf("%d",y+i);

        for(int k=1;k<=n;k++){
            int sum = 0;
            int MaxNum = NN;
            for(int i=0; ifor(int j=0; j0;
                    for(int kk=0; kkabs(x[i]-x[kk])+abs(y[j]-y[kk]);
                    sort(dis,dis+n);

                    for(int kk=0; kkif(sum < MaxNum)
                        MaxNum = sum;
                }

            }
            if(k!=n)
                printf("%d ",MaxNum);
            else
                printf("%d", MaxNum);

        }
    }
    return 0;
}

你可能感兴趣的:(校园招聘)