华为机测,本来以为是2个hard + 1个medium;
结束后一查才发现,第一题就是hard,不讲武德啊!
好家伙,三个hard!华为机测容易的时代一去不复返了!!!
第一题: 最大值子矩阵
题目给出一个矩阵,里面的值有正有负,
求一个子矩阵,使得这个子矩阵框住的值最大,并返回最大值。
//这一题的思路是:由一维的连续子数组最大和,然后扩展到上下界的遍历,则可计算二维问题。//复杂度O(N^3) import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int rows = sc.nextInt();//行数 int cols = sc.nextInt();//列数 int res = Integer.MIN_VALUE; int[][]matrix = new int[rows][cols]; for(int i=0; i<=rows-1; ++i){ for(int j=0; j<=cols-1; ++j){ matrix[i][j] = sc.nextInt(); } } for(int begin = 0; begin<=rows-1; ++begin){//上边界 int[] line = new int [cols];//每一列之和 //修改上边界之后,要清空重新开始 for(int end = begin; end<= rows-1; ++end){//下边界 //计算列元素和 for(int j=0; j<=cols-1; ++j){ line[j] += matrix[end][j];//下边界每向下一行,就计算更新下line[]数组的值 } res = Math.max(res,line[0]); int sum = 0; for(int j=0; j<=cols-1; ++j){ sum += line[j]; res = Math.max(res,sum);//取最大 if(sum<0)sum=0;//小于零,置零 //这样意味着最终的值可能是负数 } } } System.out.println(res); } } //3 4 //-3 5 -1 5 //2 4 -2 4 //-1 3 -1 3 ////20
第二题: 逃跑路径长度
给出一个矩阵,里面是秒数,
从左上出发,到右下结束,每走一格,所有秒数都减一
求逃跑路径的长度(路径长度==逃跑总时间,一秒一格)
import java.io.BufferedInputStream; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; class Node{ int x; int y; int hop; public Node(int x, int y, int hop) { this.x = x; this.y = y; this.hop = hop; } } public class Main { static int row,col; static int[] dx={-1,1,0,0}; static int[] dy={0,0,1,-1}; private static int getAns(int[][] grid){ if (grid[0][0]<=0){ return -1; } int[][] minTime=new int[row][col]; for (int i = 0; i < row; i++) { Arrays.fill(minTime[i],Integer.MAX_VALUE); } Queue<Node> queue=new LinkedList<>(); queue.add(new Node(0,0,0)); while (!queue.isEmpty()){ Node node=queue.poll(); int x=node.x; int y=node.y; int hop=node.hop; // System.out.println(x+" "+y+" "+hop); if (minTime[x][y]<=hop||grid[x][y]<hop)continue; minTime[x][y]=hop; if (x==row-1&&y==col-1)return hop; for (int i = 0; i < dx.length; i++) { int nextX=dx[i]+x; int nextY=dy[i]+y; if (!inGrid(nextX,nextY))continue; queue.add(new Node(nextX,nextY,hop+1)); } } return -1; } private static boolean inGrid(int x,int y){ return x>=0&&x<row&&y>=0&&y<col; } //Main主函数 public static void main(String[] args) { Scanner s=new Scanner(new BufferedInputStream(System.in)); row=s.nextInt(); col=s.nextInt(); int[][] grid=new int[row][col]; for (int i = 0; i <row ; i++) { for (int j = 0; j < col; j++) { grid[i][j]=s.nextInt(); } } System.out.println(getAns(grid)); } }
//如果想快速取分,直接return row+col-2, 可以得到90%的分,惊不惊喜!!!
第三题: 任务规划(类似AOE)
题目给出多个任务,包括每个任务需要的时间,
以及所有任务依赖的其他任务,依赖的其他任务完成后才能执行本任务,
求完成所有任务所需的时间,如果任务循环依赖等待则返回-1
import java.util.ArrayList; import java.util.HashSet; import java.util.Scanner; // 【任务类型划分】 // 将任务划分为task+run+finish三个状态:task是未达到运行条件的任务; run是正在运行的任务; finish是已完成的任务; // 由于task需要保存任务的多个依赖项,且后续需要remove删除依赖,所以使用ArrayList<HashSet<Integer>> // run和finish均使用 HashSet<Integer> // 【模拟思路】 // 以时间time为主线,一秒一秒加,直到全部运行完则返回总时间;如果总时间大于1000则认为是有循环依赖返回-1 // 【状态转换】 // 1) 检查所有finish,去掉task中的依赖项;(初始状态下,finish有-1) // 2) 检查每个task,将依赖为空的,放到run里面(hashSet自动去重了) // 3) 遍历所有run,把对应的任务ArrayList<Integer> time用时都减一; // 4) 如果任务剩余时间减到0,就放入finish // 5) 循环的最后判断finish的size是否是num+1(有一个-1),如果是就跳出循环、所有任务结束 // 6) 时间+1,从头循环 public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int num = sc.nextInt(); ArrayList<HashSet<Integer>> task = new ArrayList<HashSet<Integer>>();//存task任务依赖 ArrayList<Integer> time = new ArrayList<>();//存时间 for(int i=0; i<=num-1; ++i){ String str1 = sc.next(); String str2 = sc.next(); String[] strs = str1.split(","); HashSet<Integer> task1 = new HashSet<>(); task.add(task1); for(String s:strs){ task.get(i).add(Integer.valueOf(s)); } //任务 time.add(Integer.valueOf(str2)); } HashSet<Integer> finish = new HashSet<>();//完成的任务 finish.add(-1); HashSet<Integer> run = new HashSet<>(); int res = 0; for(;res<=1000;res++){ //检查finish for(Integer f:finish){ for(int i=0;i<=num-1;++i){ task.get(i).remove(f); } } for(int i=0;i<=num-1;++i){ if(task.get(i).size()==0)run.add(i); } for(Integer r:run){ int newValue = time.get(r)-1; time.set(r,newValue); if(time.get(r)==0)finish.add(r); } if(finish.size()==num+1){ res++; break; } } if(res == 1001)res =-1; System.out.println(res); } } //===用例1===// //6 //3,5 2 //5 3 //4 5 //1 2 //0 3 //-1 1 ////16 //===用例2===// //3 //-1 1 //2 2 //1 3 ////-1 //===用例3===// //3 //-1 1 //-1 2 //-1 3 ////3