Kattis Challenge "Grid"

Published: April 28, 2018 | Last Modified: May 2, 2025

Tags: kattis coding challenge

Categories: Java

Solved using a non-recursive version of BFS. Runs in pretty good time.

Problem

My Solution

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
class Kattis_Grid {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] temp = br.readLine().split(" ");
        int rows = Integer.parseInt(temp[0]);
        int cols = Integer.parseInt(temp[1]);
        /*
        This program uses 1D arrays instead of 2D arrays to enhance 
        performance at the cost of readability. This entire program will be
        micro-optimized to death.
         */
        int[] distance = new int[rows * cols];
        int[] grid = new int[rows * cols];
        /*
        Read a line as a String and store it as a character array. Subtracting 
        48 from the ASCII representation of a number will give you its decimal 
        value. This nested loop also sets the entire distance array to -1 to 
        represent that cell of the grid as being unvisited.
         */
        for (int x = 0; x < rows; x++) {
            char[] temp2 = br.readLine().toCharArray();
            for (int y = 0; y < cols; y++) {
                grid[y + cols * x] = (temp2[y] - 48);
                distance[y + cols * x] = -1;
            }
        }
        //This is the starting point.
        distance[0] = 0;
        /*
        The non-recursive implementation of BFS uses a queue (First In First Out)
        instead of a stack (First In Last Out). It checks whether a Node has 
        been discovered before enqueueing the Node rather than delaying this 
        check until the Node is dequeued from the queue.
         */
        Queue<int[]> queue = new LinkedList<>();
        /*
        I'm using a two-digit integer array in lieu of a "Node" object to shave 
        off some run time.
         */
        queue.add(new int[]{0, 0});
        int x, y, newX, newY;
        int[] current;
        while (!queue.isEmpty()) {
            //As we leave a Node we dequeue it.
            current = queue.remove();
            x = current[0];
            y = current[1];
            //Micro-optimization that saves the program one needless loop.
            if (x == rows - 1 && y == cols - 1) {
                break;
            }
            int direction = 0;
            //Check every cardinal direction.
            while (direction++ < 4) {
                switch (direction) {
                    //Up
                    case 1:
                        newX = x;
                        newY = y + grid[x * cols + y] * -1;
                        break;
                    //Down
                    case 2:
                        newX = x;
                        newY = y + grid[x * cols + y] * 1;
                        break;
                    //Left
                    case 3:
                        newX = x + grid[x * cols + y] * -1;
                        newY = y;
                        break;
                    //Right
                    case 4:
                        newX = x + grid[x * cols + y] * 1;
                        newY = y;
                        break;
                    default:
                        newX = 0;
                        newY = 0;
                        break;
                }
                /*
                Check if the direction you've moved in is within the bounds
                of the grid. If the node is within bounds,
                 */
                if (newX >= 0 && newX < rows && newY >= 0 && newY < cols) {
                    // and the node is unvisited,
                    if (distance[newX * cols + newY] == -1) {
                        // add it to the queue and update the distance matrix.
                        queue.add(new int[]{newX, newY});
                        distance[newX * cols + newY] = distance[x * cols + y] + 1;
                    }
                }
            }
        }
        /*
        Print the distance value of the bottom-right cell because that is the
        final destination in this problem.
         */
        System.out.print(distance[(rows - 1) * cols + (cols - 1)]);
    }
}