二维阵列板规则

时间:2018-03-12 23:12:20

标签: java arrays multidimensional-array

我正在做一个程序,它是关于一个"对象" (元素)根据输入在8way方向移动。 我的问题是:如何让这个元素只访问一次电路板(2D Array)?如果按规则不能移动,如何使其保持当前位置?

开始是位置(0,0) 作为输入,它得到n->尺寸数矩阵n×n,方向和t->秒。 我不知道如何实现的另一件事是输入秒,我得到输入秒和方向,因为基于那些我必须将元素移动到这个2D数组列表。

我完成了大部分程序。如果你想检查它并给我建议,我可以在这里给你我的代码。我被困在里面,我需要帮助。 我想打印未访问的单元格数。我的想法是给所有未访问过的单元格赋一个数字0,其余访问者给出数字1作为值。像cell [x] [x] = 1;最后,我计算所有数字为0的单元格作为值和打印计数。

1 个答案:

答案 0 :(得分:2)

对于特定方向的有效移动,对象必须移动到先前未占用的单元格,否则等到下一个方向。

您已定义cell[row][col]来表示访问状态; 0 =未访问,1 =已访问。最后,未访问单元格的数量将是cell元素的数量等于零。

要确定是否应移动对象,必须进行两次检查:

  1. 确保下一个位置是有效的矩阵位置(您正确执行此操作)
  2. 确保尚未访问下一个位置(将在下方显示)

    // Iterate through all k movements
    for (i = 0; i < arrTime.length - 1; i++) {
       // Move by 1 second until reach next instruction
       for (j = arrTime[i]; j < arrTime[i + 1]; j++) {
          // South East
          if (arrDirection[i].equals("SE")) {
             // Check #1 above (a valid matrix position)
             if (nCurrRow < n - 1 && nCurrCol < n - 1) {
                // Check #2 above (only move into unvisited position)
                if (cell[nCurrRow+1][nCurrCol+1] == 0) {
                   // Move, and record that cell has been visited
                   nCurrRow++;
                   nCurrCol++;
                   cell[nCurrRow][nCurrCol] = 1;
                }
             }
          }
          // Other directions following the template for South East
    
  3. 现在计算未访问的细胞:

    int unVisited=0;
    for (int i=0; i<n; i++)
       for (int j=0; j<n; j++)
          if (cell[i][j] == 0) unVisited++;
    

    编辑:用代码描述这两个问题。

    1)第一个问题与j循环有关。当前的j循环是

    for(j = arrTime[i]; j <= arrTime[i + 1]; j++)
    

    但必须是:

    for(j = arrTime[i]; j < arrTime[i + 1]; j++)
    

    它移动物体的方式比它应该再移动

    2)最后的动作没有进行。原始代码是:

    arrTime[k] = arrTime[k - 1];
    

    但必须是:

    arrTime[k] = arrTime[k - 1] + n;
    

    完成这两项更改后,两个测试用例都可以正常运行。

    编辑#2:一种减少j循环的方法

    以前,j循环会将每次迭代运行到下一个i值。在这里,我们短路并在对象无法移动时离开j循环。在第二个测试案例中,这将j次迭代的次数从50减少到28。

    for (i = 0; i < arrTime.length - 1; i++) {
        boolean canMove = true;
        for (j = arrTime[i]; j < arrTime[i + 1] && canMove; j++) {
            if (arrDirection[i].equals("SE")) {
                if (nCurrRow < n - 1 && nCurrCol < n - 1 && cell[nCurrRow + 1][nCurrCol + 1] == 0) {
                    nCurrRow++;
                    nCurrCol++;
                    cell[nCurrRow][nCurrCol] = 1;
                } else
                    canMove = false;
            } else if (arrDirection[i].equals("NE")) {
                if (nCurrRow > 0 && nCurrCol < n - 1 && cell[nCurrRow - 1][nCurrCol + 1] == 0) {
                    nCurrRow--;
                    nCurrCol++;
                    cell[nCurrRow][nCurrCol] = 1;
                } else
                    canMove = false;
            } ...
    

    编辑:寻找失败的测试用例

    查看您的新评论,t=1000000(t的最大允许值)风会发生变化是合法的。

    考虑这个非常简单的测试用例:

    3 2   (3x3 matrix, two wind changes)
    0 E   (wind blows east right away; robot moves to 0,2)
    1000000 S (wind blows south at 1000000s, robot should move to 2,2)
    

    结果应为:4,但您当前的代码将给出6,因为它不接受t = 1000000。

    如果您更改了该行:

    if(seconds >=0 && seconds<1000000 && k >=2 && k<1000000) {
    

    if(seconds >=0 && seconds<=1000000 && k >=2 && k<=1000000) {
    

    然后你得到了预期的答案4.很可能至少有一个测试用例会推动所有的输入边界,包括当t = 1000000时。

    编辑:更快的算法#2 可以通过减少if语句的数量来改进当前算法。有两个重要的改进:

    1)前一代码必须使用if来检查a)有效矩阵位置b)如果先前已访问过该位置。如果在矩阵周围创建边框,并使用值1预先填充,则可以使用1 if。由于边界,起始位置为1,1而不是0,0。 / p>

    2)在j循环内,代码不必要地查找方向。现在方向在j循环之前确定,使得j循环内的代码更快。

    未访问单元格的数量也是动态的; i循环完成后无需计算它们。我将类型更改为long,因为当n变大时,未访问的单元格的数量最多可达n*n,这需要类型为long。这可能会解决一些不正确的答案。

    如果您研究新代码,将其与旧代码进行比较,您将看到更少的if语句。在较大的测试用例下,这应该更好地扩展让我们看看是否有一些超时的测试用例得到改善。

    public class Robot {
    
    public static void main(String[] args) {
    
        Scanner in = new Scanner(System.in);
    
        int j = 0;
        int i = 0;
    
        int n = in.nextInt();
        int k = in.nextInt();
    
        int[] arrTime = new int[k + 1];
        String[] arrDirection = new String[k];
        for (j = 0; j < k; j++) {
    
            int seconds = in.nextInt();
            if (seconds >= 0 && seconds <= 1000000) {
                arrTime[j] = seconds;
            }
    
            String direction = in.next();
            arrDirection[j] = direction;
        }
        arrTime[k] = arrTime[k - 1] + n;
    
        // Add a border around the matrix with values of 1
        int N = n + 2;
        int[][] cell = new int[N][N];
        for (j = 0; j < cell.length; j++) {
            cell[0][j] = 1;  // Top border
            cell[j][0] = 1;  // Left border
            cell[j][N - 1] = 1;  // Right border
            cell[N - 1][j] = 1;  // Bottom border
        }
        int nCurrRow = 1;
        int nCurrCol = 1;
        cell[nCurrRow][nCurrCol] = 1;
        long R = n * n - 1;  // Number of remaining unvisited cells
    
        for (i = 0; i < arrTime.length - 1; i++) {
            boolean canMove = true;
            int xDir = 0;
            int yDir = 0;
            if (arrDirection[i].equals("SE")) {
                xDir = 1;
                yDir = 1;
            } else if (arrDirection[i].equals("NE")) {
                xDir = 1;
                yDir = -1;
            } else if (arrDirection[i].equals("E")) {
                xDir = 1;
            } else if (arrDirection[i].equals("N")) {
                yDir = -1;
            } else if (arrDirection[i].equals("NW")) {
                xDir = -1;
                yDir = -1;
            } else if (arrDirection[i].equals("W")) {
                xDir = -1;
            } else if (arrDirection[i].equals("SW")) {
                xDir = -1;
                yDir = 1;
            } else if (arrDirection[i].equals("S")) {
                yDir = 1;
            }
            for (j = arrTime[i]; j < arrTime[i + 1] && canMove; j++) {
                if (cell[nCurrRow + yDir][nCurrCol + xDir] == 0) {
                    nCurrRow += yDir;
                    nCurrCol += xDir;
                    cell[nCurrRow][nCurrCol] = 1;
                    R--;
                } else
                    canMove = false;
            }
        }
    
        //printArray(cell);
    
        System.out.println(R);
    
        in.close();
    }
    
    static void printArray(int[][] arr) {
        for (int row = 0; row < arr.length; row++) {
            for (int col = 0; col < arr.length; col++)
                System.out.print(arr[row][col]);
            System.out.println();
        }
    }
    }
    

    编辑#3:更高效的内存使用率;使用BitSet

    我怀疑较高的测试用例是失败的,因为在这些情况下n的值很大。当n=100000 cell数组太大导致java内存错误时,很容易测试。因此,此代码通过使用bitset使单元阵列非常紧凑。让我们看看这段代码是如何做的:

    public class Robot {
    
    public static void main(String[] args) {
    
        Scanner in = new Scanner(System.in);
    
        int j = 0;
        int i = 0;
    
        int n = in.nextInt();
        int k = in.nextInt();
    
        int[] arrTime = new int[k + 1];
        String[] arrDirection = new String[k];
        for (j = 0; j < k; j++) {
    
            int seconds = in.nextInt();
            if (seconds >= 0 && seconds <= 1000000) {
                arrTime[j] = seconds;
            }
    
            String direction = in.next();
            arrDirection[j] = direction;
        }
        if (k >= 2 && k < 1000000) {
            arrTime[k] = arrTime[k - 1] + n;
        }
    
        int N = n + 2;
        BitSet[] cell = new BitSet[N];
        for (j = 0; j < cell.length; j++)
            cell[j] = new BitSet(N);
    
        for (j = 0; j < cell.length; j++) {
            set(cell, 0, j);
            set(cell, j, 0);
            set(cell, j, N-1);
            set(cell, N-1, j);
        }
        int nCurrRow = 1;
        int nCurrCol = 1;
        set(cell,nCurrRow,nCurrCol);
        long R = n * n - 1;
    
        for (i = 0; i < arrTime.length - 1; i++) {
            boolean canMove = true;
            int xDir = 0;
            int yDir = 0;
            if (arrDirection[i].equals("SE")) {
                xDir = 1;
                yDir = 1;
            } else if (arrDirection[i].equals("NE")) {
                xDir = 1;
                yDir = -1;
            } else if (arrDirection[i].equals("E")) {
                xDir = 1;
            } else if (arrDirection[i].equals("N")) {
                yDir = -1;
            } else if (arrDirection[i].equals("NW")) {
                xDir = -1;
                yDir = -1;
            } else if (arrDirection[i].equals("W")) {
                xDir = -1;
            } else if (arrDirection[i].equals("SW")) {
                xDir = -1;
                yDir = 1;
            } else if (arrDirection[i].equals("S")) {
                yDir = 1;
            }
            for (j = arrTime[i]; j < arrTime[i + 1] && canMove; j++) {
                if (!isSet(cell,nCurrRow + yDir, nCurrCol + xDir)) {
                    nCurrRow += yDir;
                    nCurrCol += xDir;
                    set(cell,nCurrRow,nCurrCol);
                    R--;
                } else
                    canMove = false;
            }
        }
    
        //System.out.println();
        //printArray(cell);
    
        System.out.println(R);
    
        in.close();
    }
    
    static boolean isSet(BitSet[] cell, int x, int y) {
        BitSet b = cell[x];
        return b.get(y);
    }
    static void set(BitSet[] cell, int x, int y) {
        BitSet b = cell[x];
        b.set(y);
    }
    
    static void printArray(int[][] arr) {
        for (int row = 0; row < arr.length; row++) {
            for (int col = 0; col < arr.length; col++)
                System.out.print(arr[row][col]);
            System.out.println();
        }
    }
    }
    

    编辑:尝试同时阅读和处理 这种技术有时可以帮助大量输入。而不是读取所有输入,然后在第二阶段处理,在阅读时处理它。在这种情况下,不需要将数据存储在两个阵列中(一个用于到达时间,一个用于方向)。让我们看看这是否有帮助。

    public class Robot2 {
    
    static int nCurrRow = 1;
    static int nCurrCol = 1;
    static long R = 0;
    static int[][] cell;
    
    public static void main(String[] args) {
    
        Scanner in = new Scanner(System.in);
    
        int i = 0;
    
        int n = in.nextInt();
        int k = in.nextInt();
    
        // Add a border around the matrix with values of 1
        int N = n + 2;
        cell = new int[N][N];
        for (i = 0; i < cell.length; i++) {
            cell[0][i] = 1; // Top border
            cell[i][0] = 1; // Left border
            cell[i][N - 1] = 1; // Right border
            cell[N - 1][i] = 1; // Bottom border
        }
        cell[nCurrRow][nCurrCol] = 1;
        R = (long)n * n - 1; // Number of remaining unvisited cells
    
        int sec1 = in.nextInt();
        int sec2 = 0;
        String dir1 = in.next();
        String dir2;
    
        for (i = 0; i < k - 1; i++) {
    
            sec2 = in.nextInt();
            dir2 = in.next();
            move(sec2-sec1, dir1);
            dir1 = dir2;
            sec1 = sec2;
    
        }
        move(n, dir1);
    
        System.out.println(R);
    
        in.close();
    
    }
    
    static void move(int t, String dir1) {
        boolean canMove = true;
        int xDir = 0;
        int yDir = 0;
        if (dir1.equals("SE")) {
            xDir = 1;
            yDir = 1;
        } else if (dir1.equals("NE")) {
            xDir = 1;
            yDir = -1;
        } else if (dir1.equals("E")) {
            xDir = 1;
        } else if (dir1.equals("N")) {
            yDir = -1;
        } else if (dir1.equals("NW")) {
            xDir = -1;
            yDir = -1;
        } else if (dir1.equals("W")) {
            xDir = -1;
        } else if (dir1.equals("SW")) {
            xDir = -1;
            yDir = 1;
        } else if (dir1.equals("S")) {
            yDir = 1;
        }
        for (int j = 0; j < t && canMove; j++) {
            if (cell[nCurrRow + yDir][nCurrCol + xDir] == 0) {
                nCurrRow += yDir;
                nCurrCol += xDir;
                cell[nCurrRow][nCurrCol] = 1;
                R--;
            } else
                canMove = false;
        }
    }
    }
    

    编辑:BitSet和一个阶段处理的组合

    public class Robot3 {
    
    static int nCurrRow = 1;
    static int nCurrCol = 1;
    static long R = 0;
    static BitSet[] cell;
    
    public static void main(String[] args) {
    
        Scanner in = new Scanner(System.in);
    
        int i = 0;
    
        int n = in.nextInt();
        int k = in.nextInt();
    
        // Add a border around the matrix with values of 1
        int N = n + 2;
        cell = new BitSet[N];
        for (i = 0; i < cell.length; i++)
            cell[i] = new BitSet(N);
    
        for (i = 0; i < cell.length; i++) {
            set(cell, 0, i);
            set(cell, i, 0);
            set(cell, i, N-1);
            set(cell, N-1, i);
        }
        set(cell, nCurrRow, nCurrCol);
    
        R = (long)n * n - 1; // Number of remaining unvisited cells
    
        int sec1 = in.nextInt();
        int sec2 = 0;
        String dir1 = in.next();
        String dir2;
    
        for (i = 0; i < k - 1; i++) {
    
            sec2 = in.nextInt();
            dir2 = in.next();
            move(sec2-sec1, dir1);
            dir1 = dir2;
            sec1 = sec2;
    
        }
        move(n, dir1);
    
        System.out.println(R);
    
        in.close();
    
    }
    
    static void move(int t, String dir1) {
        boolean canMove = true;
        int xDir = 0;
        int yDir = 0;
        if (dir1.equals("SE")) {
            xDir = 1;
            yDir = 1;
        } else if (dir1.equals("NE")) {
            xDir = 1;
            yDir = -1;
        } else if (dir1.equals("E")) {
            xDir = 1;
        } else if (dir1.equals("N")) {
            yDir = -1;
        } else if (dir1.equals("NW")) {
            xDir = -1;
            yDir = -1;
        } else if (dir1.equals("W")) {
            xDir = -1;
        } else if (dir1.equals("SW")) {
            xDir = -1;
            yDir = 1;
        } else if (dir1.equals("S")) {
            yDir = 1;
        }
        for (int j = 0; j < t && canMove; j++) {
            if (!isSet(cell,nCurrRow + yDir, nCurrCol + xDir)) {
                nCurrRow += yDir;
                nCurrCol += xDir;
                set(cell, nCurrRow, nCurrCol);
                R--;
            } else
                canMove = false;
        }
    }
    
    static boolean isSet(BitSet[] cell, int x, int y) {
        return cell[x].get(y);
    }
    static void set(BitSet[] cell, int x, int y) {
        cell[x].set(y);
    }
    
    }
    

    编辑:用BufferedReader替换扫描仪 Scanner有可能太慢: https://www.cpe.ku.ac.th/~jim/java-io.html 这可能值得一试:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.BitSet;
    import java.util.StringTokenizer;
    
    public class Robot3 {
    
    static int nCurrRow = 1;
    static int nCurrCol = 1;
    static long R = 0;
    static BitSet[] cell;
    
    public static void main(String[] args) throws IOException {
    
        Reader.init(System.in);
    
        //Scanner in = new Scanner(System.in);
    
        int i = 0;
    
    
        int n = Reader.nextInt();
        int k = Reader.nextInt();
    
        // Add a border around the matrix with values of 1
        int N = n + 2;
        cell = new BitSet[N];
        for (i = 0; i < cell.length; i++)
            cell[i] = new BitSet(N);
    
        for (i = 0; i < cell.length; i++) {
            set(cell, 0, i);
            set(cell, i, 0);
            set(cell, i, N-1);
            set(cell, N-1, i);
        }
        set(cell, nCurrRow, nCurrCol);
    
        R = (long)n * n - 1; // Number of remaining unvisited cells
    
        int sec1 = Reader.nextInt();
        int sec2 = 0;
        String dir1 = Reader.next();
        String dir2 = "";
    
        for (i = 0; i < k - 1; i++) {
    
            sec2 = Reader.nextInt();
            dir2 = Reader.next();
            move(sec2-sec1, dir1);
            dir1 = dir2;
            sec1 = sec2;
    
        }
        move(n, dir1);
    
        System.out.println(R);
    
    }
    
    static void move(int t, String dir1) {
        boolean canMove = true;
        int xDir = 0;
        int yDir = 0;
        if (dir1.equals("SE")) {
            xDir = 1;
            yDir = 1;
        } else if (dir1.equals("NE")) {
            xDir = 1;
            yDir = -1;
        } else if (dir1.equals("E")) {
            xDir = 1;
        } else if (dir1.equals("N")) {
            yDir = -1;
        } else if (dir1.equals("NW")) {
            xDir = -1;
            yDir = -1;
        } else if (dir1.equals("W")) {
            xDir = -1;
        } else if (dir1.equals("SW")) {
            xDir = -1;
            yDir = 1;
        } else if (dir1.equals("S")) {
            yDir = 1;
        }
        for (int j = 0; j < t && canMove; j++) {
            if (!isSet(cell,nCurrRow + yDir, nCurrCol + xDir)) {
                nCurrRow += yDir;
                nCurrCol += xDir;
                set(cell, nCurrRow, nCurrCol);
                R--;
            } else
                canMove = false;
        }
    }
    
    static boolean isSet(BitSet[] cell, int x, int y) {
        return cell[x].get(y);
    }
    static void set(BitSet[] cell, int x, int y) {
        cell[x].set(y);
    }
    
    static class Reader {
        static BufferedReader reader;
        static StringTokenizer tokenizer;
    
        /** call this method to initialize reader for InputStream */
        static void init(InputStream input) {
            reader = new BufferedReader(
                         new InputStreamReader(input) );
            tokenizer = new StringTokenizer("");
        }
    
        /** get next word */
        static String next() throws IOException {
            while ( ! tokenizer.hasMoreTokens() ) {
                //TODO add check for eof if necessary
                tokenizer = new StringTokenizer(
                       reader.readLine() );
            }
            return tokenizer.nextToken();
        }
    
        static int nextInt() throws IOException {
            return Integer.parseInt( next() );
        }
    
        static double nextDouble() throws IOException {
            return Double.parseDouble( next() );
        }
    }
    }
    

    编辑:使用Set来存储已访问的单元格 事实证明,当n很大时,创建BitSet是一个昂贵的过程。大约1.4s只是为了创建BitSets数组。因此数组不起作用,并且BitSet创建很慢。经过一番思考后,我意识到常规的HashSet<Long>应该能够存储被访问的单元格,并且创建它的成本不同。

    public class Robot4 {
    
    static int nCurrRow = 1;
    static int nCurrCol = 1;
    static long R = 0;
    static Set<Long> cell;
    static long N;
    
    public static void main(String[] args) throws IOException {
    
        Reader.init(System.in);
    
        int i = 0;
        int n = Reader.nextInt();
        int k = Reader.nextInt();
    
        // Add a border around the matrix with values of 1
        N = n + 2L;
        cell = new HashSet<Long>(1000000);
    
        for (i = 0; i < N; i++) {
            set(0, i);
            set(i, 0);
            set(i, n+1);
            set(n+1, i);
        }
        set(nCurrRow, nCurrCol);
    
        R = (long)n * n - 1; // Number of remaining unvisited cells
    
        int sec1 = Reader.nextInt();
        int sec2 = 0;
        String dir1 = Reader.next();
        String dir2 = "";
    
        for (i = 0; i < k - 1; i++) {
    
            sec2 = Reader.nextInt();
            dir2 = Reader.next();
            move(sec2-sec1, dir1);
            dir1 = dir2;
            sec1 = sec2;
    
        }
        move(n, dir1);
    
        System.out.println(R);
    
    }
    
    static void move(int t, String dir1) {
        boolean canMove = true;
        int xDir = 0;
        int yDir = 0;
        if (dir1.equals("SE")) {
            xDir = 1;
            yDir = 1;
        } else if (dir1.equals("NE")) {
            xDir = 1;
            yDir = -1;
        } else if (dir1.equals("E")) {
            xDir = 1;
        } else if (dir1.equals("N")) {
            yDir = -1;
        } else if (dir1.equals("NW")) {
            xDir = -1;
            yDir = -1;
        } else if (dir1.equals("W")) {
            xDir = -1;
        } else if (dir1.equals("SW")) {
            xDir = -1;
            yDir = 1;
        } else if (dir1.equals("S")) {
            yDir = 1;
        }
        for (int j = 0; j < t && canMove; j++) {
            if (!isSet(nCurrRow + yDir, nCurrCol + xDir)) {
                nCurrRow += yDir;
                nCurrCol += xDir;
                set(nCurrRow, nCurrCol);
                R--;
            } else
                canMove = false;
        }
    }
    
    static boolean isSet(int x, int y) {
        return cell.contains(indexId(x,y));
    }
    static void set(int x, int y) {
        cell.add(indexId(x,y));
    }
    static long indexId(int x, int y) {
        return x*N+y;
    }
    
    static class Reader {
        static BufferedReader reader;
        static StringTokenizer tokenizer;
    
        /** call this method to initialize reader for InputStream */
        static void init(InputStream input) {
            reader = new BufferedReader(
                         new InputStreamReader(input) );
            tokenizer = new StringTokenizer("");
        }
    
        /** get next word */
        static String next() throws IOException {
            while ( ! tokenizer.hasMoreTokens() ) {
                tokenizer = new StringTokenizer(
                       reader.readLine() );
            }
            return tokenizer.nextToken();
        }
    
        static int nextInt() throws IOException {
            return Integer.parseInt( next() );
        }
    
        static double nextDouble() throws IOException {
            return Double.parseDouble( next() );
        }
    }
    }