2020-12-24
문제
0과 1로만 이루어진 행렬 A와 행렬 B가 있다. 이때, 행렬 A를 행렬 B로 바꾸는데 필요한 연산의 횟수의 최솟값을 구하는 프로그램을 작성하시오.
행렬을 변환하는 연산은 어떤 3*3크기의 부분 행렬에 있는 모든 원소를 뒤집는 것이다. (0 -> 1, 1 -> 0)
입력
첫째 줄에 행렬의 크기 N M이 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 행렬 A가 주어지고, 그 다음줄부터 N개의 줄에는 행렬 B가 주어진다.
출력
첫째 줄에 문제의 정답을 출력한다. 만약 A를 B로 바꿀 수 없다면 -1을 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;
public class TemplateA {
static int n,m;
static int arrN[][],arrM[][];
public static boolean flip(int startA, int startB) {
// arrN 과 arrM이 같지 않을때 뒤집을 함수
if(startA > n || startB+3 > m) {
return false;
}
//범위를 넘어간다면, 같아질 수 없음으로 false를 리턴함
//true 문을 먼저 적으면 overhead 발생할 수 있어 함수식 작성시
//false조건이 먼저 있어야함
for(int i = startA; i <= startA + 2; i++) {
for(int j = startB; j <= startB + 2; j++) {
arrN[i][j]= 1-(arrN[i][j]);
}
}
return true;
//함수에 들어간 i 와 j에 2씩 더해준 값이 3 * 3 의 크기임으로 그 범위까지
//바꾸어주고 그후 true를 리턴헤줌
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
arrN = new int[n][m];
arrM = new int[n][m];
for(int i = 0; i < n; i++) {
String row = br.readLine();
for(int j = 0; j < m; j++) {
arrN[i][j] =row.charAt(j)-'0';
}
}
for(int i = 0; i < n; i++) {
String row = br.readLine();
for(int j = 0; j < m; j++) {
arrM[i][j] =row.charAt(j)-'0';
}
}
// arrN 과 arrM 에 주어진 값을 넣어주는 과정
int count = 0;
loop : for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(arrN[i][j] != arrM[i][j]) {
if(flip(i,j)) {
count++;
//같지 않을 경우 지속적으로 범위내에서 3 * 3 뒤집기를 해줌
}else {
count = -1;
break loop;
//flip 함수가 false를 출력할 경우임
//count는 -1로 변경한 후 반복문 탈출
}
}
}
}
System.out.println(count);
br.close();
}
}
출처링크 : www.acmicpc.net/problem/1080