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