Algorithm & PS/Problem Solving

백준 - 1080. 행렬

Dlise 2024. 1. 31. 09:27

앞으로는 정리하면 좋을 것 같다고 생각이 드는 문제에 대해 글을 남길 계획이다.

 

1080. 행렬

 

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

 

1080번: 행렬

첫째 줄에 행렬의 크기 N M이 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 행렬 A가 주어지고, 그 다음줄부터 N개의 줄에는 행렬 B가 주어진다.

www.acmicpc.net

 

입출력

 

설명

행렬의 크기 N, M과 두 행렬 A, B가 주어진다.

A를 B와 동일하게 만들기 위해 3*3 크기의 부분 행렬을 뒤집는 최소 연산 횟수를 출력해야 한다.

만약 동일하게 만들 수 없다면 -1을 출력해야 한다.

 

접근

실버 1 문제라서 무난하겠거니 생각했는데 문제를 아무리 읽어도 방법이 떠오르지 않아서 고생했다.

대부분의 문제들이 그렇듯 눈으로는 정말 쉽게 풀겠는데 막상 코드 작성은 하지 못하는 경우였다.

 

주변에서 그리디 알고리즘(Greedy Algorithm)이라는 힌트를 받고서야 풀 수 있었다.

 

풀이

3*3 크기의 부분 행렬에 있는 모든 원소를 뒤집는다는 점을 활용해야 한다.

이 말의 의미는 아래와 같이 3*3 미만 크기의 행렬만큼 뒤집을 수 없다는 것이다.

따라서 (0,0) 위치의 원소를 뒤집기 위해선 반드시 (1,1)을 중심으로 하는 부분 행렬을 뒤집어야 한다.

 

즉, 중심에서 왼쪽 위의 값이 같으면 뒤집지 않고 다르면 뒤집으면 된다.

 

그 후 A와 B를 비교했을 때 내용이 다르다면 동일하게 만들 수 없다고 판단해 -1을 반환한다.

 

코드

initMap: 행렬을 입력 값에 맞게 초기화한다.

changeMap: 왼쪽 위의 값이 다르면 3*3 만큼을 뒤집는다.

checkMap: 결과를 비교한다.

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

public class Main {

    static boolean[][] map;
    static boolean[][] result;
    static int N;
    static int M;

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

        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        map = initMap(br);
        result = initMap(br);

        int answer = 0;
        for(int i = 1; i < N-1; i++) {
            for(int j = 1; j < M-1; j++) {
                if(map[i-1][j-1] != result[i-1][j-1]) {
                    changeMap(i, j);
                    answer++;
                }
            }
        }

        if(checkMap()) {
            bw.append(String.valueOf(answer));
        } else {
            bw.append("-1");
        }
        bw.flush();
    }

    static boolean[][] initMap(BufferedReader br) throws IOException {
        boolean[][] map = new boolean[N][M];
        for(int i = 0; i < N; i++) {
            String temp = br.readLine();
            for(int j = 0;j < M; j++){
                map[i][j] = temp.charAt(j) - '0' != 0;
            }
        }
        return map;
    }

    static void changeMap(int n, int m) {
        for(int i = n-1; i <= n+1; i++) {
            for(int j = m-1; j <= m+1; j++) {
                map[i][j] = !map[i][j];
            }
        }
    }

    static boolean checkMap() {
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < M; j++) {
                if(map[i][j] != result[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }
}