import java.util.Scanner; /** * Calculates percent of floated island terrain by water */ public class Solution { /** * Gets data from standard input */ private Scanner input = null; /** * Matriz de alturas del mapa de la isla */ private double[][] mapa = 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); // Leer el mapa de la isla if ( leerMapa() ) { leerImprimirProyecciones(); } else { System.out.println("Invalid data"); } // Close the standard input this.input.close(); } /** * Lee el mapa dado desde la entrada estandar * @return true si el mapa se pudo leer correctamente */ public boolean leerMapa() { // Leer las dimensiones de la matriz y crearla int filas = this.input.nextInt(); int columnas = this.input.nextInt(); if ( filas > 0 && columnas > 0 ) { this.mapa = new double[filas][columnas]; // Leer las filas for ( int fila = 0; fila < this.mapa.length; ++fila ) { // Leer cada columna en la fila actual for ( int columna = 0; columna < this.mapa[fila].length; ++columna ) { // Leer el valor de la celda this.mapa[fila][columna] = this.input.nextDouble(); } } return true; } else { return false; } } public void leerImprimirProyecciones() { // Mientras hayan proyecciones while ( this.input.hasNextInt() ) { // Leer el año y el nivel del mar int año = this.input.nextInt(); double nivelMar = this.input.nextDouble(); // Calcular el porcentaje inundado de la isla double porcentaje = calcularPorcentajeInundado(nivelMar); // Imprimir el año, nivel del mar y porcentaje inundado System.out.printf("%d: %.1f %.1f%%%n", año, nivelMar, porcentaje); } } /** * Calcular el porcentaje inundado de la isla: */ public double calcularPorcentajeInundado(double nivelMar) { // Necesito una matriz para marcar las celdas inundadas byte[][] inundado = new byte[ this.filas() ][ this.columnas() ]; // Marco cuales celdas estan inundadas de acuerdo al nivel del mar inundarMatriz(inundado, nivelMar); // Cuento la cantidad de celdas inundadas long celdasInundadas = contarCeldasInundadas(inundado); // Retorno la cantidad de celdas inundadas entre la cantidad total de celdas en el mapa long totalCeldas = this.filas() * this.columnas(); return 100.0 * celdasInundadas / totalCeldas; } public int filas() { return this.mapa.length; } public int columnas() { return this.mapa[0].length; } /** * Marco cuales celdas estan inundadas de acuerdo al nivel del mar: */ public void inundarMatriz(byte[][] inundado, double nivelMar) { // Ir por cada celda del borde del mapa // Primera fila y ultima fila for ( int columna = 0; columna < columnas(); ++columna ) { // Tratar de inundarla inundarCelda( inundado, 0, columna, nivelMar ); inundarCelda( inundado, filas() - 1 , columna, nivelMar); } // Primera y ultima columna for ( int fila = 1; fila < filas() - 1; ++fila ) { // Tratar de inundarla inundarCelda( inundado, fila, 0, nivelMar ); inundarCelda( inundado, fila, columnas() - 1, nivelMar); } } // Tratar de inundar una celda: public void inundarCelda(byte[][] inundado, int fila, int columna, double nivelMar ) { if ( esCeldaValida(fila, columna ) ) { // Si la celda no ha sido visitada if ( inundado[fila][columna] == 0 ) { // Si la celda esta por debajo del nivel del mar if ( this.mapa[fila][columna] <= nivelMar ) { // La marco como inundada inundado[fila][columna] = -1; // Tratar de inundar las vecinas inundarCelda( inundado, fila - 1, columna - 1, nivelMar ); inundarCelda( inundado, fila - 1, columna , nivelMar ); inundarCelda( inundado, fila - 1, columna + 1, nivelMar ); inundarCelda( inundado, fila , columna - 1, nivelMar ); inundarCelda( inundado, fila , columna + 1, nivelMar ); inundarCelda( inundado, fila + 1, columna - 1, nivelMar ); inundarCelda( inundado, fila + 1, columna , nivelMar ); inundarCelda( inundado, fila + 1, columna + 1, nivelMar ); } // De lo contrario else { // La marco como NO inundada inundado[fila][columna] = 1; } } } } public boolean esCeldaValida(int fila, int columna) { return fila >= 0 && fila < this.filas() && columna >= 0 && columna < this.columnas(); } public long contarCeldasInundadas(byte[][] inundado) { // Cuenta la cantidad de -1 en la matriz long cantidad = 0; // Leer las filas for ( int fila = 0; fila < inundado.length; ++fila ) { // Leer cada columna en la fila actual for ( int columna = 0; columna < inundado[fila].length; ++columna ) { // Leer el valor de la celda if ( inundado[fila][columna] == -1 ) { ++cantidad; } } } return cantidad; } }