문제
0과 1로만 이루어진 행렬 A와 행렬 B가 있다. 이때, 행렬 A를 행렬 B로 바꾸는데 필요한 연산의 횟수의 최솟값을 구하는 프로그램을 작성하시오.
행렬을 변환하는 연산은 어떤 3 ×3 크기의 부분 행렬에 있는 모든 원소를 뒤집는 것이다. (0 → 1, 1 → 0)
입력
첫째 줄에 행렬의 크기 N M이 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 행렬 A가 주어지고, 그다음줄부터 N개의 줄에는 행렬 B가 주어진다.
출력
첫째 줄에 문제의 정답을 출력한다. 만약 A를 B로 바꿀 수 없다면 -1을 출력한다.
내가 푼 풀이
- 0과 1로 이루어진 행렬을 변환하는 연산은 3x3크기의 부분행렬의 모든원소를 뒤집는 것이다.
- 주어진 행렬이 연산이 불가능한 경우: N < 3 , M < 3
- 이 문제는 한 원소를 기준으로 3x3의 부분 원소를 변환했다.
- 행렬이 1행 1열 -> 1행 m열 -> n행 m열 순으로 인덱스를 접근한다면, 이미 접근한 인덱스는 연산이 이미 완료됐다고 본다.
- 인덱스로 접근할 때 행렬 A[n][m] 값과 B[n][m]값이 다르다면, n과 m기준으로 3x3의 부분행렬을 연산한다.
- n-2행 m-2열까지 모두 순회 후, 연산결과 출력
import Foundation
let inputs = readLine()!.split(separator: " ").map{ Int($0)! }
var a = [[String]]()
var b = [[String]]()
var result = 0
// 배열 입력받기
for i in 1...inputs[0]*2 {
var arr = Array(readLine()!).map{ String($0) }
if i <= inputs[0] {
a.append(arr)
} else {
b.append(arr)
}
}
// 배열의 크기가 연산가능한 크기보다 작다면
// 배열 a 와 b가 서로 다르다면, a는 b가 될 수 없으므로 -1
// 배열 a 와 b가 서로 같다면, a는 이미 b이므로 0 출력
if a.count < 3 || a[0].count < 3 {
for i in 0..<a.count {
let arr1 = a[i]
let arr2 = b[i]
if a[i] != b[i] {
result = -1
}
}
print(result)
} else {
// 행은 n-2 까지, 열은 m-2 까지 순회
// a[n][m] != b[n][m] 이면 연산
for i in 0..<a.count-2 {
for j in 0..<a[0].count-2 {
var str1 = a[i][j]
var str2 = b[i][j]
if str1 == str2 {
continue
} else {
result += 1
for k in 0..<3 {
for n in 0..<3 {
if a[i+k][j+n] == "1" {
a[i+k][j+n] = "0"
} else {
a[i+k][j+n] = "1"
}
}
}
}
}
}
// 연산결과 a와 b가 완전히 같은지 비교
for i in 0..<a.count {
let arr1 = a[i]
let arr2 = b[i]
if a[i] != b[i] {
result = -1
}
}
print(result)
}
'코딩테스트 > 백준' 카테고리의 다른 글
BOJ-2293 동전 1 Swift (0) | 2023.05.18 |
---|---|
BOJ-2437 저울 Swift (0) | 2023.05.18 |
BOJ-9465 스티커 Swift (1) | 2023.05.17 |
BOJ-2864 5와 6의 차이 Swift (1) | 2023.05.17 |
BOJ-11000 강의실 배정 Swift (1) | 2023.05.17 |