문제 링크 : https://www.acmicpc.net/problem/1080
문제
0과 1로만 이루어진 행렬 A와 행렬 B가 있다. 이때, 행렬 A를 행렬 B로 바꾸는데 필요한 연산의 횟수의 최솟값을 구하는 프로그램을 작성하시오.
행렬을 변환하는 연산은 어떤 3*3 크기의 부분 행렬에 있는 모든 원소를 뒤집는 것이다. (0 -> 1, 1 -> 0)
입력
첫째 줄에 행렬의 크기 N M이 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 행렬 A가 주어지고, 그다음 줄부터 N개의 줄에는 행렬 B가 주어진다.
출력
첫째 줄에 문제의 정답을 출력한다. 만약 A를 B로 바꿀 수 없다면 -1을 출력한다.
풀이
이 문제와 같이 뒤집기 문제의 핵심은 동일한 뒤집기를 두 번 실행할 필요가 없다는 것이다. 똑같은걸 두 번 뒤집어 봤자 결과는 처음과 동일하기 때문이다.
행렬의 크기는 50 x 50 이기 때문에 완전 탐색으로 뒤집는 모든 경우의 수를 계산하려면 2^2500번을 해야하니 이 문제는 반드시 규칙성을 찾아야 한다.
발견한 규칙은 이러하다
그림이 조잡하긴 하지만.. 4x4 행렬에 대해서 모든 뒤집기를 실행한 결과이다.(뒤집기마다 색이 다른거임!!)
그림을 잘 보면 빨간색 부분은 처음에 딱 한번 실행한 건데 고대로 남아있는 걸 볼 수 있다.
그렇다!! 맨 위 오른쪽 부분은 원하는 행렬의 숫자와 다르면 무조건! 뒤집어야 한다.
이를 뒤집고 나면, 그다음은 노란색 처음 부분(0,1)이 빨간색과 동일한 상황에 처한다.
그다음은 주황색(1,0).. 그다음은 초록색(1,1)이 된다.
만약 이 과정을 거쳤는데도 원하는 행렬이 만들어지지 않는다면, 이 행렬은 안 되는 행렬이다.(뒤집을 건 다 뒤집은거니까..)
그렇다면 다른 크기의 행렬은 어떨까??
눈치챘겠지만, 0~(n-2) x 0~(n-2)에 속하는 칸들에 대해 위와 같은 과정을 적용하면 된다.
코드로 살펴보자!
소스 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <iostream>
#include <algorithm>
using namespace std;
int a[50][50];
int b[50][50];
void reverse(int y, int x) {
for (int i = y - 1; i <= y + 1; i++) {
for (int j = x - 1; j <= x + 1; j++) {
a[i][j] = 1 - a[i][j];
}
}
}
int main()
{
//입력
int n, m; scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%1d", &a[i][j]);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%1d", &b[i][j]);
}
}
int ans = 0;
for (int i = 0; i < n - 2; i++) {
for (int j = 0; j < m - 2; j++) {
if (a[i][j] != b[i][j]) {
ans++;
reverse(i + 1, j + 1);
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (a[i][j] != b[i][j]) {
printf("%d", -1);
return 0;
}
}
}
printf("%d", ans);
return 0;
}
|
cs |
코드는 간단하다. for 0 ~ n-2 과정을 거치면서 원하는 행렬 원소와 다르면 그 부분 3x3 행렬을 뒤집으며 반복한 후,
원하는 행렬과 일치하는지 확인하면 끝!
개발환경 : Visual Studio 2019
지적, 조언 언제든지 환영입니다~~
'백준 문제풀이' 카테고리의 다른 글
백준 11728번 배열 합치기 (0) | 2020.01.02 |
---|---|
백준 2873번 롤러코스터 (0) | 2020.01.02 |
백준 1783번 병든 나이트 (0) | 2020.01.01 |
백준 2875번 대회 or 인턴 (0) | 2020.01.01 |
백준 1744번 수 묶기 (0) | 2020.01.01 |