백준 알고리즘 정리 (구현 - 1996번)

황제연·2024년 3월 23일
0

알고리즘

목록 보기
13/169
post-thumbnail
문제번호제목난이도
1996지뢰 찾기실버 5

1996번 지뢰 찾기

해결코드

import java.io.*;
import java.util.*;


public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int n = Integer.parseInt(br.readLine());
        String[][] field = new String[n][n];
        for (int i = 0; i < n; i++) {
            String[] input = br.readLine().split("");
            for (int j = 0; j < n; j++) {
                field[i][j] = input[j];
            }
        }

        int[][] score = new int[n][n];
        int[] dx = {0,0,-1,1,-1,1,-1,1};
        int[] dy = {-1,1,0,0,-1,-1,1,1};


        for(int i=0; i<n; i++){
            for (int j = 0; j < n; j++) {
                if(!field[i][j].equals(".")){
                    score[i][j] = -1;
                    int count = Integer.parseInt(field[i][j]);
                    for (int k = 0; k < 8; k++) {
                        if(j+dx[k] >= 0 && i + dy[k] >= 0 && j+dx[k] < n && i+dy[k] < n){
                            if(field[i+dy[k]][j+dx[k]].equals(".")){
                                score[i+dy[k]][j+dx[k]] += count;
                            }
                        }
                    }
                }
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(score[i][j] == -1){
                    bw.write("*");
                }else if(score[i][j] >= 10){
                    bw.write("M");
                }else{
                    bw.write(score[i][j] +"");
                }
            }
            bw.write("\n");
        }

        
        br.close();
        bw.close();
    }
}

해결방법

  1. 일단 문자와 숫자가 섞여있기에 String형 2차원 배열 vs Char형 2차원 배열중 고민을 했다.
  2. 문제의 목표와 진행 과정을 살펴보면, "."인 경우와 아닌 경우로만 구분하면 되기 때문에, String형 2차원 배열을 선택하였다
  3. 어제 풀었던 방식은 총 8개의 if문을 선언해서 팔방을 다 체크하는 방식으로 구현했었다. 이 방식은 내가 과거에 그래프 탐색 유형 BFS문제를 풀때의 방식이다.
  4. 3번같이 풀면 저부분만 치는데 10분 이상은 나온다... 따라서 일반적으로 많은 사람들이 쓰고, 더 직관적이며 효율적인 dx, dy 배열을 활용하는 방식을 선택하였다
  5. 왼쪽부터 오른쪽으로 '상,하,좌,우,좌상,우상,좌하,우하'순으로 dx,dy배열을 선언하였다
  6. 이제 탐색을 시작한다. input 배열에서 현재 위치의 값이 "."이 아니면 숫자가 있다는 것인데, 이 문제에서 숫자가 있으면 그 위치에 지뢰가 있는 것이다.
  7. *은 문자고 문제 출력은 숫자도 포함해야한다. 그렇다면 정답 배열도 String형으로 해야하는가 고민을 하게 되었다.
  8. 하지만 다음 진행 과정에서 현재 위치의 숫자 만큼 팔방의 값을 증가시켜야하는데, String형으로 하면 그렇게 하기 쉽지 않다.
  9. 그래서 int형 배열을 만들고 만약 지뢰가 있으면 '-1'로 넣자고 정의하였다.
  10. -1을 넣은 뒤에 숫자를 파싱해서 count변수에 넣어두고, 총 8번 순회를 돌아 팔방 범위에 다음 작업을 진행한다
  11. 먼저 범위를 벗어나는지 체크를 해야한다. 그 다음 한가지를 더 체크한 뒤에 값을 더해줘야한다
  12. 만약 내 팔방의 범위에 "."가 아니라 숫자가 있다면 -1인 값에 더해지거나, 전혀 예상과 다른 결과를 초래할 수 있다
  13. 따라서 내 팔방의 범위가 "."인 경우만 count만큼 int형 배열에 더해준다
  14. 위 과정을 n*n만큼 순회한다
  15. 이어서 완성된 int형 배열을 순회하는데 만약 -1이면 "*"을 출력하고 10 이상이면 "M", 둘다 아니면 그 위치의 숫자를 출력한다.

문제 링크:

백준-지뢰찾기

profile
Software Developer

0개의 댓글