import java.util.Scanner; /** * Esta clase se encarga de determinar el menor número de movimientos, o gasto de energía, que soluciona una pantalla o nivel del juego * y la columna que se despeja al realizar estos movimiento */ public class ModelSolution { /** * Gets data from standard input */ private Scanner input = null; /** * Crea una matriz que será modificada para contener la pantalla del juego en el nivel correspondiente */ private int pantalla[][]= new int[1][1]; /** * Crea un arreglo que contendrá todas las filas en las que no haya ni un solo cero */ private int error[]= new int[1]; /** * Crea un arreglo que contendrá la energía necesaria para despejar cada columna */ private int solutionCols[]= new int[1]; /** * Start the execution of the solution * @param args Command line arguments */ public static void main(String args[]) { ModelSolution modelsolution = new ModelSolution(); modelsolution.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); //Leer las dimensiones y crear la matriz del juego, la matriz de errores y la de energía int rows= input.nextInt(); int cols= input.nextInt(); int partida[][]= new int[rows][cols]; int errores[]= new int[partida.length]; int columnasSolucion[]= new int[partida[0].length]; this.pantalla= partida.clone(); this.error= errores.clone(); this.solutionCols= columnasSolucion.clone(); //Llenar la matriz llenarPantalla(); //Ver si hay filas sin ceros y reportar si las hay if(!todoEnOrden()) { //Leer el arreglo de las columnas con error y reportar cuáles tienen errores for(int index= 0; index < error.length; index++) { if (error[index] == 1) { System.out.print("Invalid row"); System.out.printf(" %d", index + 1); System.out.println(); } } } else { //Imprimir la solución printSolution(); } // Close the standard input this.input.close(); } /** * Método que llena la matriz pantalla con los valores que recibe de la entrada y que representan * la presencia o ausencia de autos u otros obstáculos */ public void llenarPantalla() { //Llena para cada fila los valores por cada columna for (int row= 0; row < this.pantalla.length; row++) { for (int col= 0; col < this.pantalla[0].length; col++) { this.pantalla[row][col]= input.nextInt(); } } } /** * Método que determina si todas las fias poseen al menos un cero, en caso contrario, el nivel no tiene solución. * Almacena el número de cada fila carente de ceros. * @return true si todas las filas tienen al menos un cero, false en caso contrario */ public boolean todoEnOrden() { boolean todoEnOrden= true; //Contar el número de ceros en la fila int cuentaCerosRow= 0; //Revisar para cada fila por cada columna si hay ceros for(int row= 0; row < this.pantalla.length; row++) { for (int col= 0; col < this.pantalla[0].length; col++) { if (this.pantalla[row][col] == 0) { cuentaCerosRow++; } //Si llega al final de la fila y la cantidad de ceros es cero entonces no es una fila válida if( col == this.pantalla[0].length - 1 && cuentaCerosRow == 0) { todoEnOrden= false; //Registrar la fila inválida registraErrores(row); } } //Reiniciar el conteo de ceros cuentaCerosRow= 0; } return todoEnOrden; } /** * Método que guarda el número de cada fila sin ceros */ public void registraErrores(int row) { //Guardar la información en la casilla que representa a la fila de la pantalla this.error[row]= 1; } /** * Método que imprime la solución a la pantalla o nivel, es decir, el número menor de movimientos o energía necesarios * para despejar una columna y el número de la columna que se despeja */ public void printSolution() { //Llamar método que imprima ambas cosas printEnergyAndCol(); } /** * Método para determinar y posteriormente imprimir el número mínimo de movimientos o energía necesarios * para despejar una columna y el número de las columnas que se despejan con dicha cantidad de movimientos. * Si varias columnas se despejan con la misma cantidad de movimientos o energía, que es la mínima para toda la pantalla, * se imprimen los números de todas estas columnas */ public void printEnergyAndCol() { //Calcular la solución int energy= this.pantalla.length * (this.pantalla[0].length - 1); int energyCol= 0; int colSolution= 0; //Ver por cada columna la cantidad mínima de energía, o movimientos, para despejarla for(int col= 0; col < this.pantalla[0].length; col++) { for(int row= 0; row < this.pantalla.length; row++) { //Si la columna es la primera if(col == 0) { //Burca el próximo cero adelante energyCol += findSpaceForward(row, col); } //Si la columna es la última else if(col == this.pantalla[0].length - 1) { //Busca el próximo cero atrás energyCol += findSpaceBackward(row, col); } //En otro caso else { //Busca el próximo cero adelante //Busca el próximo cero atrás //Escoge el más cercano if(findSpaceForward(row, col) > findSpaceBackward(row, col)) { energyCol += findSpaceBackward(row, col); } else { energyCol += findSpaceForward(row, col); } } } //Guardar la energía para la columna que acaba de analizarse this.solutionCols[col]= energyCol; if(energyCol <= energy) { energy= energyCol; colSolution= col; } energyCol= 0; } //Imprimir los movimientos System.out.printf("%d", this.solutionCols[colSolution]); for(int index= 0; index < this.solutionCols.length; index++) { if (this.solutionCols[index] == this.solutionCols[colSolution]) { //Imprimir la columna solución System.out.printf(" %d", index + 1); } } } /** * Método para determinar la cantidad mínima de energía a utilizar, o movimientos, para mover el obstáculo indicado * una casilla hacia adelante. * @param row es la fila en la que se encuentra el obstáculo * @param col es la columna en la que se encuentra el obstáculo * @return el número de movimientos o energía para mover el obstáculo una casilla a la derecha */ public int findSpaceForward (int row, int col) { //Si hay un obstáculo if(this.pantalla[row][col]== 1) { for(int currentCol = col; currentCol < this.pantalla[0].length - 1; currentCol++) { if(this.pantalla[row][currentCol] == 1) { //Si el siguiente está ocupado, pasar al siguiente if(this.pantalla[row][currentCol + 1] == 1) { } //Si el siguiente no está ocupado, devolver la distancia del siguiente al solicitado else { return (currentCol + 1 - col); } } } //Si no hay ningún espacio libre (un cero) después, la distancia es máxima return this.pantalla[0].length; } //Si no hay obstáculo, no se usa energía else { return 0; } } /** * Método para determinar la cantidad mínima de energía a utilizar, o movimientos, para mover el obstáculo indicado * una casilla hacia atrás. * @param row es la fila en la que se encuentra el obstáculo * @param col es la columna en la que se encuentra el obstáculo * @return el número de movimientos o energía para mover el obstáculo una casilla a la izquierda */ public int findSpaceBackward (int row, int col) { //Si hay un obstáculo if(this.pantalla[row][col]== 1) { for(int currentCol = col; currentCol > 0; currentCol--) { if(this.pantalla[row][currentCol] == 1) { //Si el anterior está ocupado, pasa al anterior if(this.pantalla[row][currentCol - 1] == 1) { } //Si el anterior no está ocupado, devuelve la distancia del anterior y el solicitado else { return (col - (currentCol - 1)); } } } //Si no hay ningún espacio libre (un cero) antes, la distancia es máxima return this.pantalla[0].length; } //Si no hay obstáculo no se usa energía else { return 0; } } }