import java.util.Scanner; /** * Replace this JavaDoc comment for the purpose of this class */ public class Solution { /** * Gets data from standard input */ private Scanner input = null; /** * Variable that will reference the model class */ private TrainLineGame trainLineGame = null; /** * Start the execution of the solution * @param args Command line arguments */ public static void main(String args[]) { Solution solution = new Solution(); solution.run(); } /** * Run the solution. This method is called from main() */ public void run() { // Create object to read data from standard input this.input = new Scanner(System.in); // Variable to store the amount of rows of the matrix int rows = input.nextInt(); // Variable to store the amount of columns of the matrix int cols = input.nextInt(); // Consumes a blank line input.nextLine(); // Creates a new object and a reference to the model class trainLineGame = new TrainLineGame(rows, cols); // Calls the method to read the matrix trainLineGame.readMatrix(input); // Calls the method to print the result trainLineGame.printResult(); // Close the standard input this.input.close(); } } /** * Class that will do all the methods needed to find the row of the * matrix that will need the least amount of energy to be freed, and also * how much energy it needs. * * It also determines if a matrix is valid or not and prints either the error * messages if it is invalid, or the row that need the least amount of energy * and the amount of energy if it is indeed valid. */ /*public*/ class TrainLineGame { /** * Attribute to store the amount of rows the matrix has */ private int rows = 0; /** * Attribute to store the amount of cols the matrix has */ private int cols = 0; /** * Reference to the matrix of the game */ private int[][] obstaclesMatrix = null; /** * Constructor method of the class. Receives the rows and columns * of the matrix as the parameter and sets the attributes of the class/ * @param rows the amount of rows of the matrix * @param cols the amount of columns of the matrix * @return a reference to the object of the type of the class */ public TrainLineGame( int rows, int cols) { // Sets the attribute rows to the parameter received this.rows = rows; // Sets the attribute cols to the parameter received this.cols = cols; // Creates a matrix of the size wanted by the user and a reference to it this.obstaclesMatrix = new int[rows][cols]; } /** * Method that runs all the positions of the matrix and fill every * position with an integer that it reads from the input. * * @param input a reference to the Scanner class */ public void readMatrix( Scanner input) { // The cycle goes line by line filling the matrix for ( int row = 0; row < this.rows; ++row ) { // The cycle goes column by column for ( int col = 0; col < this.cols; ++col ) { // The matrix is filled with what it reads from the input this.obstaclesMatrix[row][col] = input.nextInt(); } } } /** * Method to print how much energy is needed to free a column * and what column has the minimum amount of energy needed * It calls the method is valid to determine the validity of the matrix * received, if it is valid, it calls the method to determine the result * and then prints it. */ public void printResult() { // Variable that will store the result of the class String result = ""; // Calls the method isValid to determine if the matrix has a solution if ( isValid()) { // Result gets the minimun amount of moves needed to free a column, // and what column or columns take that amount of energy // Example "2 4 5", when 2 is the minimum amount of moves, and 4 // and 5 the columns that require two moves to be freed result = determineResultMinimumEnergyAndColumn(this.obstaclesMatrix); } // Prints the result, it will either be "" or the amount // of energy needed and the corresponding column System.out.printf("%s", result); } /** * Method to determine if a matrix is valid or not. * A matrix is defined as valid if in every line it has * at least one "0", that is, a place where a car can be moved * in order to free that line. * * @return true if all rows have at least one "0", false otherwise */ private boolean isValid() { // Variable to store the validity boolean isValidMatrix = true; // Loop to go through the lines for ( int row = 0; row < this.rows; ++row ) { // Variable to store if a particular line is valid boolean isValidLine = false; // The cycle goes column by column for ( int col = 0; col < this.cols; ++col) { // Determine if the line has at least one "0" if ( this.obstaclesMatrix[row][col] == 0) { isValidLine = true; } } // If none of the columns had a "0" if ( ! isValidLine) { // Prints that the row is invalid System.out.printf("Invalid row %d %n", row + 1); // Sets the validity of the matrix to false isValidMatrix = false; } } // Returns either true or false return isValidMatrix; } /** * Method to determine what column or columns need the least * amount of moves in order to be freed, and how many moves that * it. * * @param matrix a reference to the attribute obstaclesMatrix, * it could have been used with "this" but I thought this way it * was more readable * @return a formatted String with the amount of energy needed to * free a column and the corresponding column or columns */ private String determineResultMinimumEnergyAndColumn(int[][] matrix) { // Array to store the amount of moves that each column // needs in order to be freed int[] energies = new int[this.cols]; // The cycle goes line by line filling the matrix for ( int row = 0; row < this.rows; ++row ) { // The cycle goes column by column for ( int col = 0; col < this.cols; ++col) { // Determines if the current cell is not free if ( matrix[row][col] != 0 ) { // Calls the method to determine how many moves the row needs to be // freed by moving to the left and to the right. Then it compares the // two values and add the lowest one to the amount of energy that // column needs to be freed energies[col] += Math.min( runToTheRight(row, col), runToTheLeft(row, col)); } } } // Calls the method to format a String with the lowestEnergy and column/columns // and returns the formatted String received return determineLowestEnergy( energies); } /** * Method that runs the columns 1 by 1 to the right and checks if one of them * is a 0, if it is, returns to amount of moves that are needed to get there. * If it reaches the end of the matrix and does not find a 0, it returns * a 1000, so that the minimum moves needed is not * this value. * * @param row the current row that is being checked * @param col the current column that is being checked * @return the amount of moves needed to free a cell if a 0 is found, * Integer.MAX_VALUE if not */ private int runToTheRight(int row, int col) { // Cycle that runs through all the cells to the right of the // coordinates received until it finds a "0" or reached the end // of the matrix for ( int moves = 1; col + moves <= this.cols - 1; ++moves ) { // Checks if it found a 0 if ( this.obstaclesMatrix[row][col + moves] == 0) { // Returns the amount of moves it took to find a 0 return moves; } } // If it got to this point, it means that it did not find a 0 return Integer.MAX_VALUE; } /** * Method that runs the columns 1 by 1 to the left and checks if one of them * is a 0, if it is, returns to amount of moves that are needed to get there. * If it reaches the end of the matrix and does not find a 0, it returns * a thousand, so that the minimum moves needed is not * this value. * * @param row the current row that is being checked * @param col the current column that is being checked * @return the amount of moves needed to free a cell if a 0 is found, * Integer.MAX_VALUE if not */ private int runToTheLeft(int row, int col) { // Cycle that runs through all the cells to the left of the // coordinates received until it finds a "0" or reached the end // of the matrix for ( int moves = 1; col - moves >= 0; ++moves ) { // Checks if it found a 0 if ( this.obstaclesMatrix[row][col - moves] == 0) { // Returns the amount of moves it took to find a 0 return moves; } } // If it got to this point, it means that it did not find a 0 return Integer.MAX_VALUE; } /** * Method to determine which of the columns needs the least energy * It receives and array with the amount of moves each column needs * in order to be freed, it determines which of the values is the lowest * and then concatenates the amount of moves needed and the corresponding * column in a String * * @param energies array with the amount of moves each column needs * @return a concatenated String with the format: lowestEnergy needed + " " * + lowestColumn1 + " " + lowestColumn2 + " "... */ private String determineLowestEnergy( int[] energies) { // Variable to determine which of the values is the lowest // Firstly it sets the lowest to the first value int lowestEnergy = energies[0]; // String to store the concatenated result String formattedResult = " "; // Cycle to go checking the energies of each column for ( int col = 1; col < energies.length; ++col) { // If one of the energies is lower than the // previous lowest if ( energies[col] < lowestEnergy) { // Changes the new lowest energy to the // energy of the current column lowestEnergy = energies[col]; } } // Concatenates the lowest energy to the result string formattedResult = lowestEnergy + " "; // Runs all the columns to see of more than one have the lowest // energy possible, if so, it concatenates them to the result for ( int col = 0; col < energies.length; ++col) { // If the energy of this column is equals to the lowest if ( energies[col] == lowestEnergy) { // Concatenates the index of this column to the result formattedResult += (col + 1) + " "; } } // Returns a formatted string with the lowest energy needed to // free a column and the corresponding column or columns return formattedResult; } }