首页 > 其他分享 >微众银行笔试-大湮灭术

微众银行笔试-大湮灭术

时间:2023-04-14 12:00:12浏览次数:26  
标签:right 湮灭 nums int 笔试 length dp 微众

大湮灭术

题目说明

世间充斥看正负两种能量,正能量对人体有益,而负能量对人体是有害的。已知地图上有n个排应一列的地域,每个地域的能量都不一样,可以用一个数字来代表某个地域中正负能量的数,正数代表正能量比负能量多,反之亦然。

现在大漫灭术的卷轴只剩下了两个,你可以对任何一个连续的区域使用大湮灭术,使用之后,无论该连续区域中能量有多少,都会清0。你希望天地间的正能量最多,请问船使得正能量最多为多少。(如果天地间都是正能量,不使用卷轴也是可以的)

解题思路

首先要明确一个问题,此处需要求的一个是区间的最大负能量,如果只是通过动态规划纯粹的从左向右遍历的话,得到的只是包含该位置在内的左边区间的最大负能量dp_left[]。因此为了解决这个问题,还需要从右向左再遍历一次dp_right[],分别获得基于该位置的左右区间最大负能量后,相加再减掉一份当前位置的值后(计算左右区间都用了nums[i]),便获得了区间最大负能量dp[],遍历获得区间最小值first。在获取到first之后通过判定其是否小于0来决定是否需要使用大湮灭术(将这部分区间清零),还是直接返回结果结束。

然后通过暴力方法(暂时没有想到更好的定位方法)来确定是哪一段区间的和等于first值,当tmp == first时跳出循环。将这一段的数值置0,至此第一遍大湮灭术使用。

第二次使用大湮灭术的基本流程和第一次的流程基本相同,同样要经历通过获取左右区间最大负能量,获取区间最大负能量,决定是否使用大湮灭术这几个步骤。如果是k次使用大湮灭术的话,可以将其用函数写出来,可以减少代码的复杂程度,提高可读性、复用性并便于维护debug。

具体代码

package Test;

import java.util.*;

public class test {

    public static void main(String[] args) {
        // 假定以这个数组为例代表能力
        int[] nums = {-2, -2, -2, 1, -2, 3, 3, 3, 3, -2, -2, 1, -2, 3, 4};

        // 通过dp寻找左区间最大负能量
        int[] dp_left = new int[nums.length];
        // 左区间dp初始化
        dp_left[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
            dp_left[i] = Math.min(nums[i], dp_left[i - 1] + nums[i]);
        }
        
        // 通过dp寻找右区间最大负能量
        int[] dp_right = new int[nums.length];
        // 右区间dp初始化
        dp_right[dp_right.length - 1] = nums[dp_right.length - 1];
        for (int i = nums.length - 2; i >= 0; i--) {
            dp_right[i] = Math.min(nums[i], dp_right[i + 1] + nums[i]);
        }

        // 左右子区间相加获得该位置最小子区间,记得减去一次当前nums[i]
        int[] dp = new int[nums.length];
        int first = Integer.MAX_VALUE;
        for (int i = 0; i < nums.length; i++) {
            dp[i] = dp_left[i] + dp_right[i] - nums[i];
            first = Math.min(first, dp[i]);
            System.out.printf(dp[i] + " ");
        }
        System.out.println();
        
        // 不需要使用湮灭术直接结束
        if(first > 0) {
            int sum = 0;
            for (int num : nums) {
                sum += num;
            }
            System.out.println(sum);
            return;
        }

        // 大湮灭术,通过暴力的手段定位区间后把区间内能力清零
        int start = 0;
        int end = 0;
        int tmp = 0;
        for (int i = 0; i < nums.length; i++) {
            for (int j = i; j < nums.length; j++) {
                tmp = 0;
                for (int t = i; t <= j; t++) {
                    tmp += nums[t];
                }
                if (tmp == first) {
                    start = i;
                    end = j;
                    break;
                }
            }
            if (tmp == first) {
                break;
            }
        }

        for (int i = start; i <= end; i++) {
            nums[i] = 0;
        }

        // 第二次使用湮灭术之前要将之前的变量重置
        Arrays.fill(dp_left, 0);
        int second = Integer.MAX_VALUE;
        for (int i = 1; i < nums.length; i++) {
            dp_left[i] = Math.min(nums[i], dp_left[i - 1] + nums[i]);
        }

        Arrays.fill(dp_right, 0);
        dp_right[dp_right.length - 1] = nums[dp_right.length - 1];
        for (int i = nums.length - 2; i >= 0; i--) {
            dp_right[i] = Math.min(nums[i], dp_right[i + 1] + nums[i]);
        }


        for (int i = 0; i < nums.length; i++) {
            dp[i] = dp_left[i] + dp_right[i] - nums[i];
            second = Math.min(second, dp[i]);
            System.out.printf(dp[i] + " ");
        }
        System.out.println();

        // 判定是否需要使用第二次大湮灭术
        if (second > 0) {
            int sum = 0;
            for (int num : nums) {
                sum += num;
            }
            System.out.println(sum);
            return;
        }

        start = 0;
        end = 0;
        tmp = 0;
        for (int i = 0; i < nums.length; i++) {
            for (int j = i; j < nums.length; j++) {
                tmp = 0;
                for (int t = i; t <= j; t++) {
                    tmp += nums[t];
                }
                if (tmp == second) {
                    start = i;
                    end = j;
                    break;
                }
            }
            if (tmp == second) {
                break;
            }
        }

        for (int i = start; i <= end; i++) {
            nums[i] = 0;
        }

        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        System.out.println(sum);
        return;


    }

}

(这段代码也无从验证是不是对的了,只能说自己搞了几个样例验证了一下好像也没问题,过程有将区间最小和的dp数组打印出来)

标签:right,湮灭,nums,int,笔试,length,dp,微众
From: https://www.cnblogs.com/xccx-0824/p/17317892.html

相关文章

  • 11.1金山游戏开发笔试
    intmain(){ inti; (i=1,i=10)?i++||++i:++i; printf("%d",i); getchar();}答案:11.解释:逗号表达式,又称为“顺序求值运算符”。逗号表达式的一般形式为表达式1,表达式2,表达式3……表达式n求解过程是:先求解表达式1,再求解表达式2,...。整个逗号表达式的值是最后一个表达式n的......
  • 前端笔试遇到的两个编程题
    倒计时:在倒计时不超过一天的代码varhour=document.querySelector(".hour");  varminute=document.querySelector(".minute");  varsecond=document.querySelector(".second");//截止的时间  varinputTime=+newDate("2023-4-0820:0......
  • 笔试题
    importjava.util.*;publicclassMain{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);StringBuffernum3=newStringBuffer();Stringnum=scanner.next();StringBuffernum2=newStringBuffe......
  • 杭电计算机复试笔试题
    2018杭电计算机复试笔试题1简单题题目1:杭电实验室会定期去电影院看电影,按照惯例,每个成员需要先抽一个号码。给出n个人的名字,各抽取一个数字,自己用一种数据结构存取人的名字和抽取数字信息(票数)1.定义一种数叫丑数,其因子除1外只有2.3.5的倍数,(例如4,10,是丑数,11,13不是),输出......
  • Math笔试
    varnum=23.34;console.log(Math.ceil(num));//返回大于等于num的最小整数24console.log(Math.floor(num));//返回小于等于num的最大整数23console.log(Math.round(num));//返回与num最接近的整数(四舍五入)23console.log(Math.abs(num));//返回num的绝对值23......
  • 解数独 【笔试题】
    本题虽然是困难但是难度不大写的时候也是有经验classSolution{publicvoidsolveSudoku(char[][]board){backtrack(board,0,0);}public......
  • 关于两道笔试题的思考
    1.在32位机器上正确的输出是?structNode{boolval1;intval2;charstr[1023];};Node*p=newNode();std::cout<<sizeof(p)<<std::endl;std::cout......
  • 笔试题
    1.用一个生活案例,描述面向对象这个概念你跟她说“去倒茶”,她就会把茶到好;你说“老婆.衣服.颜色=红”,她就自己去把红色衣服换上。当你老婆做饭时,她会产生一个“帮忙”事件,......
  • 百度2020校招Web前端工程师笔试卷(第三批)(大题21~23)
    <!DOCTYPEhtml><html><head><metacharset="UTF-8"><style>body,ul,li,select{margin:0;padding:0;box-sizing:border-box......
  • 89.神州数码、华为、东软笔试题
    89.神州数码、华为、东软笔试题1.2005年11月15日华为软件研发笔试题。实现一单链表的逆转。2.编码实现字符串转整型的函数(实现函数atoi的功能),据说是神州数码笔试题......