广联达-笔试AK题解-2023/09/06

第一题

【简单分析】:

1. 对于订单i,只有两种可能,要么送,要么不送。

2. 若骑手选择送第i个订单,那么在需要耗时time[i],会影响到后面的i+1 ~ n个订单是否能选择。

因此,为了简化dp过程,遍历的方向应该从后往前,这样做当选择第i个订单时,后面的i+1 ~ n个订单的状态可以转移过来

【状态定义】:

dp[i][0] 表示考虑i ~ n个订单,不送第i个订单,骑手能获得的最大收入

dp[i][1] 表示考虑i ~ n个订单,送第i个订单,骑手能获得的最大收入

例如:若n=15,dp[9][0] 表示考虑第9~15个订单,不送第9个订单,骑手能获得的最大收入

【状态转移】:

//不送第i个订单,那么骑手能获得的最大收入与 i+1 ~ n这些订单的选择与否有关

dp[i][0] = Math.max(dp[i+1][0], dp[i+1][1])

// 送第i个订单,那么骑手能获得的最大收入与 index ~ n这些订单的选择与否有关

// 其中第index个订单表示若骑手送完第i个订单耗时time[i]后最近可以选择的订单

// 第index个订单可能不存在,因为送完第i个订单后耗时time[i],但是后面没订单可以接了

dp[i][1] = cost[i];

if (checkOrderExist(index)){

dp[i][1] = Math.max(dp[index][0] + cost[i], dp[index][1] + cost[i]);

}

【最终答案】:

Math.max(dp[0][0], dp[0][1])

public static void main(String[] args) throws IOException {
        // 输入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] ss1 = br.readLine().split(" ");
        String[] ss2 = br.readLine().split(" ");
        String[] ss3 = br.readLine().split(" ");

        int[][] array = new int[n][3];
        for(int i=0;i<n;i++){
            // 收到第i个订单的时间
            array[i][0] = Integer.parseInt(ss1[i]);
            // 选择送第i个订单的耗时
            array[i][1] = Integer.parseInt(ss2[i]);
            // 选择送第i个订单的收入
            array[i][2] = Integer.parseInt(ss3[i]);
        }
        // 按照收到订单时间的顺序升序排序
        Arrays.sort(array, Comparator.comparingInt(o -> o[0]));

        /* DP */
        // 开long,因为题目给的数据范围很大(单笔订单的收入小于等于1e9)
        long[][] dp = new long[n+1][2];
        dp[n][0] = dp[n][1] = 0;
        for(int i=n-1;i>=0;i--){
            // 不拿当前外卖
            dp[i][0] = Math.max(dp[i+1][0], dp[i+1][1]);
            // 只拿当前外卖,其他的外卖不拿
            dp[i][1] = array[i][2];
            // 拿当前外卖,同时也考虑拿其他外卖
            if((long)array[i][0] + array[i][1] > 1e9){
                continue;
            }
            int index = binSearch(array, array[i][0] + array[i][1]);
            if(index < n && array[index][0] >= array[i][0] + array[i][1]){
                dp[i][1] = Math.max(dp[i][1], dp[index][0] + array[i][2]);
                dp[i][1] = Math.max(dp[i][1], dp[index][1] + array[i][2]);
            }
        }
        System.out.println(Math.max(dp[0][0], dp[0][1]));
    }
    /**
     * 在arr[0~n][0]中找到大于等于target的最小下标
     */
    private static int binSearch(int[][] arr, int target) {
        int l = 0;
        int r = arr.length-1;
        while(l < r){
            int mid = l + ( r - l) / 2;
            if(arr[mid][0] >= target){
                r = mid;
            }
            else{
                l = mid + 1;
            }
        }
        return l;
    }

第二题

1. 由题意得,目标是让所有的士兵外观一致,而我们能做的就是:划出一个偶数长度的区间,从中间切一半,让右半边士兵的外观同化左半边

    2. 那么能影响所有士兵外观的就只能是最右边的那个士兵

    例:如果前n-1个士兵的外观一模一样,第n个士兵独一无二。虽然我们只有1个士兵外观不一致,但是我们没办法用1次操作使得所有士兵外观一致,因为我们的操作方向是从右影响左。

    3. 以最右边的士兵为外观目标,即target = arr[n]

    j指针从最右往左走,直到遇到arr[j] != target,这说明第j+1~n个士兵的外观都一样,以这些士兵为右半边让他们直接同化左半边的士兵。

    例: [1,2,3,4,5,6,7,8,8,8] -> [1,2,3,4,8,8,8,8,8,8] -> [8,8,8,8,8,8,8,8,8,8]

public static void main(String[] args) throws IOException {
        // 输入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] ss = br.readLine().split(" ");
        int[] arr = new int[n];
        for(int i=0;i<n;i++){
            arr[i] = Integer.parseInt(ss[i]);
        }

        // 双指针 + 贪心
        int ans = 0;
        int target = arr[n-1];
        int i = n-1;
        int j;
        while(i >= 0){
            j = i;
            while(j >= 0 && arr[j] == target){
                j--;
            }
            if(j < 0){
                break;
            }
            ans++;
            int rightCount = n - j - 1;
            i = j-rightCount;
        }
        System.out.println(ans);
    }

#笔试##秋招##广联达#
全部评论
请问产品需求岗也要敲代码吗
点赞 回复 分享
发布于 2023-09-12 19:45 北京
过面了吗兄弟
点赞 回复 分享
发布于 2023-09-12 18:22 香港

相关推荐

头像
01-12 14:44
已编辑
百度_高级研发工程师
今天看到了某平台攻击牛友的帖子,段段今天打算为牛友们说句话,我们的努力到底有没有意义。&nbsp;(原文复述:感觉牛客就是当年那群做题区毕业了开始找工作还收不住那股味,颇有一种从年级第一掉到年纪第二后抱怨考不上大学的区味)&nbsp;&nbsp;粗鄙,无礼,傲慢,攻击,在这里我没有看到任何有用的分析,我只看到了屁股决定脑袋的攻击,我只看到了嫉妒和眼红。一、去医院不看病你去逛街吗&nbsp;去医院你不去看病你去逛街吗?去加油站不加油你去抽烟吗?去部队你不训练战斗技能你去养老吗?来牛客你不努力求职你来干什么来了。&nbsp;牛客本身就是个求职平台,大家分享有用的知识,分享面经,分享offer,分享求职经验的,来牛客不就干这个来了吗?有什么问题吗?...
给个好点的工作吧啊啊...:不知道我看的是不是和博主同样的帖子,我记得原帖是表达的是有些匿名老是发几十万的offer侮辱价,然后就有牛友觉得凡尔赛了导致后面的评论有些偏激。我觉得这个最近闫学晶那个事情有点类似了,她说他儿子一年只能赚七八十万家庭生活都难以为继,不说普通家庭,多少大厂的程序员都赚不到这个数字,大部分家庭看到这种发言肯定会难受的一p,生活的担子又这么重,人都是需要发泄情绪的,互联网就是个极佳的载体,所以很多人直接就喷她了,人在情绪发泄的时候是不思考的,否则就不叫发泄了。然后还有一个点,段哥假定了这些喷的人全都是“躺平的”,这点可能有失偏颇,很多人一直在努力,但是始终缺乏天时地利人和的某一个条件,这点相信段哥找工作的过程中深有体会。绝大部分人都以结果的失败去否认了努力的全过程,可能只是别人努力的方向错了。就像一次面试,可能你准备了很久,结果面试官就是比较奇葩,一直问没有学习到的领域或知识点,然后有人凭一个挂掉的结果就直接给你扣了一个“躺平”的帽子,觉得挂掉是你不够努力,您心里滋味如何?再说点近点的,我也是od,多少同事深夜无偿加班,涨过一分工资吗?多少外包的技术大牛因为学历被困在外包,连od都进不去,这些人难道不努力吗?只是限制与生活、公司制度等等之类的无奈罢了。说到努力,又想到李家琦79元眉笔事件,这么多年有没有认真工作?有没有涨工资?他嘴里说出来是那么的理所当然,打工牛马都知道“任劳任怨”,“认真工作”真能涨工资?只干活不发声就等着被摘果子吧,企业里永远都是“汇报杰出者”升的最快(当然不是所有企业),这种事情相信段哥包括我甚至大部分od都经历过。最近辞职回老家,和老爸散步每次他都会感慨街上的蔬菜小贩多不容易,他们晚上就窝在那种三轮小货车的驾驶室里,腿都伸不直,我们这里晚上零下了,只盖一条薄毛毯,始终舍不得住我们镇上几十块的酒店,因为一车蔬菜就赚几百块顶多一千而且要卖好久,这样的例子还有太多了。这种芸芸众生可能辛苦了一天之后,打开手机看到网上的凡尔赛发言,跟风喷了几句发泄情绪,我觉得这种人不应该扣上“躺平”的帽子。我觉得大部分正常人都是努力的,或者曾经努力过,但世界上有太多努力解决不了的无奈了,甚至说你都没有那个努力的机会,不过正因如此,才显得坚持不懈的努力奋斗之人的难得可贵,认清生活的真相后仍然热爱生活,敢于直面现实的淋漓。
点赞 评论 收藏
分享
评论
2
21
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务