본문 바로가기
Baekjoon/[4] 브루트 포스

[백준] 1018번 체스판 다시 칠하기 JAVA (자바) 풀이

by Poorm 푸름 2024. 4. 11.

문제 1018 

M x N 크기 보드 (검정색 & 흰색)

보드를 잘라서 8 x 8 크기의 체스판으로 만들기

체스판 규칙 : 검적생 흰색 번갈아서 칠할 것

 

잘라낸 보드 판을 체스판 규칙에 맞게 다시 칠해야 하는 최소 횟수를 구하시오

 

 

[입력]

 

 :  첫째 줄에 N과 M ( 8보다 크거나 같고 50보다 작거나 같은 자연수)

 :  둘째 줄부터 N개의 줄 보드 각 행의 색이 주어진다 ( B = 검은색, W = 흰색 )

 

 

 [출력]


 :  다시 칠해야 하는정사각형 개수

 

     

 

 

 [참고]

 

1. 맨 처음 시작 판을 기준으로 번갈아 색을 칠할 것!

 

  • 첫 시작판을 한가지 색으로 고정하자!
    흰색판일 경우로만 진행하는 것 
    흑과 백 경우의 수가 2개 이므로 boolean을 사용!

    (0과 1로 사용해도 괜찮다)

  • 반대색은 무조건 64 - (count)
    위에서 흰색판일 경우로 진행했다 = count 라고 할 때
    반대색인 검정판으로 시작할 경우의 색칠 수는 흰색판 기준 색칠 수의 반대
    => 64(전체 판 개수) - count 해주기

  • result = Integer.MAX_VALUE;
    초기 비교 경우 result를 가장 낮은 0으로 초기화 한다면 min 값을 구할 때 계속해서 0에 머문다
    초기 비교를 위해 가장 높은 값으로 초기화 한다
  • 자릿수가 2개 뿐이라 어차피 비교 대상은 하나이기 때문에 일정한 공차를 가진다
    ex) 16 ▶ 한수 ( 공차 = 5 ), 98 ▶ 한수 ( 공차 = -1 )

 

2. 백의 자리 숫자부터 계산할 것

 

  • 100의 자리라면?

    - 공차 범위
    : - 4 ~ 4


    - 범위가 1000까지인데 1000은 한수가 아니므로 111 ~ 999까지 검사하면 된다

 

 [코드]

 

import java.util.*;
import java.io.*;
public class Main{
    static boolean board[][]; 
    static int result =Integer.MAX_VALUE;
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        board = new boolean[N][M];
        
        for(int i=0; i<N; i++){ // 행
            String str = br.readLine();
            for(int j=0; j<M; j++){ //열
                board[i][j]=(str.charAt(j)=='W');
            }
        }
        
        //체스판 만들기
        for(int i =0; i<=N-8; i++){
            for(int j=0; j<=M-8;j++){
                result = Math.min(count(i,j), result);
            }
        }
        
        System.out.println(result);
    }
    
    public static int count(int x, int y){
       
        int count = 0; 
        boolean color = board[x][y];
        
        for(int i =x; i <x+8; i++){
            for(int j =y; j<y+8; j++){
                if(board[i][j]!=color){
                    count++;
                }
                color = !color;
            }
            color = !color;
        }
        
        return Math.min(count, 64-count);
    }
}

 

 

 [해설]
     

 :  static boolean board[][]; 
    static int result =Integer.MAX_VALUE;  result 최대로 초기화

 

 :  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st;
        
 :  st = new StringTokenizer(br.readLine());
    int N = Integer.parseInt(st.nextToken());  가로 길이
    int M = Integer.parseInt(st.nextToken());  세로 길이
    board = new boolean[N][M];  흑과 백 간편한 비교를 위해 boolean 설정
        
 :  for(int i=0; i<N; i++){  행마다 검사
           String str = br.readLine();  문자라서 좋은 점 한줄씩 통으로 볼 수 있다
           for(int j=0; j<M; j++){  열마다 검사
                board[i][j]=(str.charAt(j)=='W');  char로 문자 하나씩 뜯어보고 W라면 true 지정
           }
    }
        
 :  for(int i =0; i<=N-8; i++){  가로 시작점 limit
           for(int j=0; j<=M-8;j++){  세로 시작점 limit
                result = Math.min(count(i,j), result);  result랑 count 돌린 것 중에 최소값
           }
    }
        
 :  System.out.println(result);  출력
        
 

 :  public static int count(int x, int y){
       
        int count = 0;  색칠횟수 초기화
        boolean color = board[x][y];  기준 컬러 정하기 ( = 첫 시작판 컬러 )
        
        for(int i =x; i <x+8; i++){  체스판 가로길이 8
            for(int j =y; j<y+8; j++){  체스판 세로길이 8
                if(board[i][j]!=color){  기준 컬러랑 다르면 색칠
                    count++;
                }
                color = !color;  판을 하나씩 옮겨갈 때마다 기준 컬러 바꿔주기 (열이동)
            }
            color = !color;  판이 다음 줄로 넘어갈 때마다 기준 컬러 바꿔주기 (행이동)
        }
        return Math.min(count, 64-count);  맨처음 정한 기준컬러와 기준컬러의 반대의 경우 색칠 수 비교
    }
}
    
 

 

 

이제 풀어보러 갈께요 :)



 

* 독학으로 익히는 코딩이라 틀린 것이 있을 수 있습니다. 오류가 있다면 댓글을 통해 알려주세요. 감사합니다. *

 

 

https://www.acmicpc.net/problem/1018

 

1018번: 체스판 다시 칠하기

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

www.acmicpc.net