【问题标题】:Find path with least maximun difference in a 2D array在二维数组中查找具有最小最大差异的路径
【发布时间】:2020-09-19 09:11:37
【问题描述】:

网络系统被定义为二维网格。网格的每个单元都有一个与之相关的路由系数。您需要从左上角向右下角发送一个数据包。

一个数据包只能在四个方向上传播——上、下、左和右,并且只有在单元格不超出边界的情况下。一个数据包需要 |C[x, y] - C[x', y']| 的能量从单元格 (x,y) 移动到单元格 (x', y'),其中 |x|表示 x 的绝对值。

数据包在任何路径上所需的努力定义为数据包沿该路径所需的最大能量。你的任务是找出数据包从左上角到右下角遍历网络所需的最小努力。

例如,数据包在给定的网格中传输,行数 N = 3,列数 M = 4。如下所述 -

{{5,1,3,2},
 {7,4,1,8},
 {6,7,5,9}}

假设数据包从 5 → 1 → 4 → 7 → 6 → 7 → 5 → 9 传输。这里每个转换所需的相应能量分别为 4、3、3、1、1、2、4。因此,路径所需的努力是 4。

输入格式

第一行包含两个用空格分隔的整数,N 和 M 分别表示行数和列数。接下来是 N 行。每行包含 M 个整数,表示

网格的行。

约束

1<=N,M<=300
1<C(i,j)<1000000

输出格式

在单行输出中,尽可能少地打印。

这是我的解决方案,但在某些测试中它会超时,所以任何人都可以提出更好的解决方案吗?

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

class Result {
    public static int getMinEffort(List<List<Integer>> C) {

        Node start = new Node(new Cell(0,0),new ArrayList<Cell>(),0);
        ArrayList<Node> nodes = new ArrayList<>();
        nodes.add(start);
        Cell destination = new Cell(C.size()-1,C.get(0).size()-1);


        while(true){
            Node active = nodes.get(0);
            nodes.remove(active);

            //break condition
            if(active.getCell().equals(destination)){
                return active.getEffort();
            }
            //checking neighbours

            active.getPath().add(new Cell(active.getCell().getX(),active.getCell().getY()));
            if(active.getCell().getX()>0){
                Cell neigh = new Cell(active.getCell().getX()-1,active.getCell().getY());
                if(!active.getPath().contains(neigh)) {
                    int effort = C.get(active.getCell().getX()).get(active.getCell().getY()) - C.get(neigh.getX()).get(neigh.getY());
                    if(effort<0)effort*=-1;
                    if(effort<active.getEffort()){
                        effort = active.getEffort();
                    }

                    nodes.add(new Node(neigh,active.getPath(),effort));
                }
            }
            if(active.getCell().getX()<C.size()-1){
                Cell neigh = new Cell(active.getCell().getX()+1,active.getCell().getY());
                if(!active.getPath().contains(neigh)) {
                    int effort = C.get(active.getCell().getX()).get(active.getCell().getY()) - C.get(neigh.getX()).get(neigh.getY());
                    if(effort<0)effort*=-1;
                    if(effort<active.getEffort()){
                        effort = active.getEffort();
                    }

                    nodes.add(new Node(neigh,active.getPath(),effort));
                }
            }
            if(active.getCell().getY()>0){
                Cell neigh = new Cell(active.getCell().getX(),active.getCell().getY()-1);
                if(!active.getPath().contains(neigh)) {
                    int effort = C.get(active.getCell().getX()).get(active.getCell().getY()) - C.get(neigh.getX()).get(neigh.getY());
                    if(effort<0)effort*=-1;
                    if(effort<active.getEffort()){
                        effort = active.getEffort();
                    }

                    nodes.add(new Node(neigh,active.getPath(),effort));
                }
            }
            if(active.getCell().getY()<C.get(0).size()-1){
                Cell neigh = new Cell(active.getCell().getX(),active.getCell().getY()+1);
                if(!active.getPath().contains(neigh)) {
                    int effort = C.get(active.getCell().getX()).get(active.getCell().getY()) - C.get(neigh.getX()).get(neigh.getY());
                    if(effort<0)effort*=-1;
                    if(effort<active.getEffort()){
                        effort = active.getEffort();
                    }

                    nodes.add(new Node(neigh,active.getPath(),effort));
                }
            }

            Collections.sort(nodes);
        }

    }

    static class Node implements Comparable<Node>{
        private Cell cell;
        private List<Cell> path = new ArrayList<>();
        private int Effort;

        public Node(Cell cell, List<Cell> path, int effort) {
            this.cell = cell;
            this.path = path;
            Effort = effort;
        }

        @Override
        public int compareTo(Node o) {
            if (o.getEffort()>Effort){
                return -1;
            }else if(o.getEffort()==Effort){
                return 0;
            }else {
                return 1;
            }
        }

        public Cell getCell() {
            return cell;
        }

        public void setCell(Cell cell) {
            this.cell = cell;
        }

        public List<Cell> getPath() {
            return path;
        }

        public void setPath(List<Cell> path) {
            this.path = path;
        }

        public int getEffort() {
            return Effort;
        }

        public void setEffort(int effort) {
            Effort = effort;
        }
    }

    static class Cell {
        private int x;
        private int y;

        public Cell(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Cell)) return false;
            Cell cell = (Cell) o;
            return x == cell.x &&
                    y == cell.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }

}

public class Solution {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        int r = scanner.nextInt();
        int c = scanner.nextInt();
        scanner.nextLine();

        List<List<Integer>> C = new ArrayList<>(r);

        for(int i = 0;i<r;i++){
            ArrayList<Integer> col = new ArrayList<>(c);
            String input = scanner.nextLine();
            String[] num = input.split(" ");
            for(int j =0;j<c;j++){
                col.add(Integer.parseInt(num[j]));
            }
            C.add(col);
        }
        int result = Result.getMinEffort(C);
        System.out.println(result);
    }
}

【问题讨论】:

    标签: dynamic path 2d minimum


    【解决方案1】:

    二分搜索的深度优先可能会有所帮助

    public class PathWithMinimumEffort {
    
    
    // **** global variable(s) ****
    static boolean vis[][]      = null;
    static boolean arrived      = false;
    static int effort           = Integer.MIN_VALUE;
    static final int[][] dirs   = { {0,1}, {1,0}, {0,-1}, {-1,0} };
    
    // **** global variables to generate gate ****
    static int left     = 0;
    static int right    = 1000000;
    
    static int dfs(int[][] heights, int row, int col, int gate) {
    
        // **** get the number of rows and columns ****
        int rows = heights.length;
        int cols = heights[0].length;
    
        // **** base case (lower-right cell) ****
        if (row == rows - 1 && col == cols - 1) {
            arrived = true;
            return heights[row][col];
        }
    
        // **** flag that this cell as been visited ****
        vis[row][col] = true;
    
        // **** recurse in all possible directions O(rows * cols)****
        for (int i = 0; i < dirs.length; i++) {
    
            // **** next cell ****
            int r = row + dirs[i][0];
            int c = col + dirs[i][1];
    
            // **** ****
            if (r >= 0 && r < rows && c >= 0 && c < cols && 
                !vis[r][c] && 
                Math.abs(heights[row][col] - heights[r][c]) <= gate) {
    
                // **** recursive call ****
                int ph = dfs(heights, r, c, gate);
    
                // **** current effort between cells ****
                int ce = Math.abs(heights[row][col] - ph);
    
                // **** update effort ****
                effort = Math.max(effort, ce);
            }
        }
    
        // **** return height of current cell ****
        return heights[row][col];
    }
    
    
    /**
     * Generate the next value of a binary search.
     * Set gate == -1 to initialize.
     */
    static int genGate(int gate) {
    
        // **** initialization ****
        if (gate == -1) {
            left    = 0;
            right   = 1000000;
            return right / 2;
        }
    
        // **** done ****
        if (left > right) {
            return gate;
        }
    
        // **** compute mid value ****
        int mid = left + (right - left) / 2;
    
        // **** go left ****
        if (arrived) {
            right = mid - 1;
        }
    
        // **** go right ****
        else {
            left = mid + 1;
        }
    
        // **** update gate ****
        gate = left + (right - left) / 2;
    
        // **** return gate ****
        return gate;
    }
    
    
    
    static int minimumEffortPath(int[][] heights) {
    
        // **** get number of rows and columns ****
        int rows = heights.length;
        int cols = heights[0].length;
    
        // **** sanity checks ****
        if (rows <= 1 && cols <= 1)
            return 0;
    
    
        // **** loop incrementing the gate ****
        // for (int gate = 0; gate < 1000000; gate++) {
    
        //     // **** loop pass initialization ****
        //     arrived = false;
        //     effort  = Integer.MIN_VALUE;
        //     vis     = new boolean[rows][cols];
    
        //     // **** start recursion  ****
        //     dfs(heights, 0, 0, gate);
    
        //     // **** if reached bottom-right cell; we are done ****
        //     if (arrived)
        //         break;
        // }
    
    
        // **** initial gate ****
        int gate = genGate(-1);
    
        // **** ****
        boolean done = false;
        do {
    
            // **** loop pass initialization ****
            arrived = false;
            effort  = Integer.MIN_VALUE;
            vis     = new boolean[rows][cols];
    
            // **** save for comparison ****
            int prevGate = gate;
    
            // **** start recursion  ****
            dfs(heights, 0, 0, gate);
    
            // **** generate new gate ****
            gate = genGate(gate);
    
            // **** matching values ****
            if (gate == prevGate)
                done = true;
        } while (!done);
    
        // **** return effort ****
        return effort;
    }
    
    
    /**
     * Test scaffolding.
     */
    public static void main(String[] args) {
    
        // **** initialize random number generator ****
        Random rand = new Random();
    
        // **** target gate ****
        int targetGate  = rand.nextInt(1000000) + 1;
    
        // **** display target gate value ****
        System.out.println("main <<< targetGate: " + targetGate);
    
        // **** loop until target gate is found ****
        boolean done    = false;
        int gate        = genGate(-1);
        do {
    
            // **** save for comparison ****
            int prevGate = gate;
    
            // **** update arrived as needed ****
            arrived = (gate >= targetGate) ? true : false;
    
            // **** new gate ****
            gate = genGate(gate);
    
            // **** matching values ****
            if (gate == prevGate)
                done = true;
        } while (!done);
    
        // **** display gate ****
        System.out.println("main <<<       gate: " + gate);
    
        // **** open scanner ****
        Scanner sc = new Scanner(System.in);
    
        // **** read number of rows and columns ****
        String[] rcStr = sc.nextLine().trim().split(",");
    
        // **** extract number of rows and columns ****
        int rows = Integer.parseInt(rcStr[0]);
        int cols = Integer.parseInt(rcStr[1]);
    
        // **** declare the array ****
        int[][] heights = new int[rows][cols];
    
        // **** loop populating the heights array ****
        for (int r = 0; r < rows; r++) {
    
            // **** ****
            String[] colsStr = sc.nextLine().trim().split(",");
    
            // **** ****
            for (int c = 0; c < cols; c++) {
                heights[r][c] = Integer.parseInt(colsStr[c]);
            }
        }
    
        System.out.println("main <<< heights:");
        for (int[] rr : heights) {
            System.out.println(Arrays.toString(rr));
        }
    
        // **** close scanner ****
        sc.close();
    
        // **** find and display minimum effort for path ****
        System.out.println("main <<< output: " + minimumEffortPath(heights));
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-06
      • 1970-01-01
      • 2019-03-31
      • 1970-01-01
      • 2017-08-08
      相关资源
      最近更新 更多