顺丰科技2021-11-21笔试

运筹优化算法岗位.
选择题(20*3分):(包含了单选和多选),考察的内容包括NP问题和P问题、运筹学基本内容(主考线性规划、最短路径算法、动态规划、分支定界等)、数据结构基础知识、python编程基础.
简答题(2*20分):
第一题是写一下单纯形算法流程.
第二题是写一下从初始点s到终止点t的Dijkstra算法流程.
编程题(2*20分):
编程题一:
完美平均
时间限制: 1000MS
内存限制: 65536KB
题目描述:
对于一个整数数组,如果其中所有数字的平均值是1,那么就称其为完美平均。现在给定一个数组,你可以往里面添加任意多个非负整数,目标是让其最终变成一个完美平均的数组。可以证明一定存在一个方案达到这样的目标。希望你算出最少需要添加多少个非负整数,可以让这个数组变成完美平均的。
输入描述
第一行一个整数n,1<=n<=100
第二行n个整数,其中任意一个数大小范围是[-10000,10000]。
输出描述
一个整数,表示最少需要添加多少个非负整数。
样例输入
3
1 1 1
样例输出
0
提示
补充样例2:
输入:
3
1 2 3
输出:
3
求解思路:这道题还是很容易的,数组平均值为1说明——“数组的和=数组的元素个数”.
先计算当前数组的和s, 元素的个数sz.  用ans来表示最少添加的非负整数的个数.
分类(s = sz, s > sz , 0< s < sz, s < 0 < sz)去讨论下
1. s = sz, 那就是不用添加了,ans = 0.
2. s > sz, 用贪心的思想去想,要想让数组的和=数组的元素个数快速成立,那肯定是加0. 那添加了几个0呢,是s - sz个. 所以 ans = s - sz.
3.0<s<sz,根据题目给的原来数组长度是<=100的,所以sz<=100, 所以只要添加一个元素就可以达到“数组的和=数组的元素个数”(添加的那个元素值为sz+1-s).所以ans=1.
4.s<0<sz,要达到数组的和=数组的元素个数”这个目标,可以每次都尝试添加最大的元素值(10000),直到sz - s <= 10000,此时添加sz - s就可以了.
#include<iostream>
#include<vector>
#include "stdio.h"
using namespace std;
int main(){
    int n, t, ans, sz;
    while(cin >> n){
        vector<int> A;
        ans = 0;
        int s = 0;
        for(int i = 0; i < n; i++){
            cin >> t;
            s += t;
            A.push_back(t);
        }
        sz = A.size();
        if(s >= sz){
            ans = s - sz;
        }
        else if(s > 0){//和小于个数并且和是大于0
            ans = 1;
        }
        else{//和小于个数并且和是小于0的.
            sz = sz + 1;
            int gap = sz - s; //加一个数看看情况
            ans ++;
            if(gap <= 10000){}
            //每次加10000
            else{
                while(gap > 10000){
                    sz = sz + 1;
                    s = s + 10000;
                    gap = sz - s;
                    ans ++;
                    if(gap <= 10000) break;
                }
            }

        }        
        cout << ans << endl;
    }
    return 0;
}
编程题二:
挑选关卡
时间限制: 1000MS
内存限制: 65536KB
题目描述:
小明正在玩一款闯关的游戏,小明将按顺序依次面对不同的关卡,每个关卡都有一个难度值。小明可以选择参与或者不参与该关卡,如果参与那么他可以获得该关卡难度值等值的积分,如果不参与那么就可以直接跳过进入下一关的选择。但是该游戏有一个限制,就是小明想参与的关卡的难度必须高于之前参与过的关卡的难度,第一关难度不做限制。现在按顺序告诉你所有关卡的难度值,你能算出小明最多可以得到多少积分吗?
输入描述
第一行一个整数n,表示关卡的总数量,1<=n<=3000
第二行n个整数,从左到右是关卡的顺序,数字大小表示关卡难度,任意数字大小范围是[1,1000000000]。
输出描述
一个整数,表示小明最多可以得到多少积分。
样例输入
3
1 3 2
样例输出
4
提示
解释:参与1,3
补充样例2:
输入:
3
3 3 3
输出:
3
补充样例3:
输入:
4
1 3 2 4
输出:
8
解释:参与1,3,4
求解思路:不知道哪里错了(没全对),我想的是用动态规划来进行求解,difnum[i]:第i个关卡的积分值,Maxnum[i]:表示以第i个关卡结尾的最大积分数.
动态转移方程应该很简单能写出来~Maxnum[i] = { max_{j : 0 ~ i-1}(Maxnum[j] + difnum[i] : difnum[i] > difnum[j]).
最大积分数 = max_{j : 0 ~ n-1}(Maxnum[j]).
#include<iostream>
#include<vector>
#include<cstring>
#include "stdio.h"
using namespace std;
int main(){
    int n;
    long long Maxnum[3005];//Maxnum[i]-以i为结尾的最大积分数
    while(cin >> n){
        vector<int> difnum(n);
        memset(Maxnum, 0, sizeof(Maxnum));
        for(int i = 0; i < n; i++)
            cin >> difnum[i];
        int i, j;
        Maxnum[0] = difnum[0]; 
        for(int i = 0; i < n; i++)
            Maxnum[i] = difnum[i];
        for(i = 1; i < n; i++){
            int flag = false;
            for(j = 0; j < i; j++){
                if((difnum[i] > difnum[j]) && (Maxnum[i] < difnum[i] + Maxnum[j])){
                    Maxnum[i] = difnum[i] + Maxnum[j];
                    flag = true;
                }
            }
            if(!flag) Maxnum[i] = difnum[i];
        }
        long long s = -1;
        for(i = 0; i < n; i++){
            if(Maxnum[i] > s)
                s = Maxnum[i];
        }
        cout << s << endl;
    }
    return 0;
}





#笔试题目##秋招#
全部评论

相关推荐

冰皮月饼_FLORRIEEE:你是准备投产品嘛?可以重新整理一下实习的bulletpoint,侧重描述你的工作所带来的结果收益,不要只写泛泛的内容(比如改写通过xx数据分析,提升xx),产品的价值并不在处理和分析数据的过程
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
4
32
分享

创作者周榜

更多
牛客网
牛客企业服务