Algorithm/알고리즘 백준 풀이
[백준] #1080 행렬 - (BF)
i009727
2020. 2. 12. 17:24
문제
https://www.acmicpc.net/problem/1080
1080번: 행렬
첫째 줄에 행렬의 크기 N M이 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 행렬 A가 주어지고, 그 다음줄부터 N개의 줄에는 행렬 B가 주어진다.
www.acmicpc.net
목적
2개의 행렬 A, B가 주어졌을때 A를 변환하여 B로 만들때의 최소 변환횟수 구하기
+ 행렬의 변환은 변환위치를 기준으로 3*3만큼의 부분행렬을 변환함.
풀이
이 문제는 내가 제대로 이해를 못한거같다.
일단 변환은 3*3의 부분행렬만 변환하는것이므로 행렬의 원소를 오른쪽위에서 왼쪽아래로 하나하나 비교하면서 다르면 변환을 진행하되 범위에 제한을 N-3, M-3으로 줘야지 3*3행렬의 변환을 진행할수있다.
그리고 일단 오른쪽위부터 시작해서 내려오므로 가장 오른쪽위인 원소 즉, 기준점은 한번 변환된다면 다음에는 변환될 일이 없으므로 그리디하게 진행함.
코드
#include <iostream>
using namespace std;
int N, M;
bool origin[51][51];
bool target[51][51];
//두개의 행렬을 같은지 비교함
bool isSame() {
for (int i=0; i<N; ++i) {
for (int j=0; j<M; ++j) {
if (origin[i][j] != target[i][j])
return false;
}
}
return true;
}
//기준점으로부터 3*3만큼의 부분행렬을 변환
void convert(int ip, int jp) {
for (int i=ip; i<ip+3; ++i) {
for (int j=jp; j<jp+3; ++j) {
if (origin[i][j])
origin[i][j] = 0;
else
origin[i][j] = 1;
}
}
}
//기본 변환함수
//원소를 하나하나 오른쪽위에서부터 아래로 비교해나감
//변환후에는 같은지 확인
int change() {
int cnt = 0;
for (int i=0; i<N-2; ++i) {
for (int j=0; j<M-2; ++j) {
if (origin[i][j] != target[i][j]) {
cnt++;
convert(i, j);
}
if (isSame())
return cnt;
}
}
return -1;
}
int main() {
cin >> N >> M;
for (int i=0; i<N; ++i) {
for (int j=0; j<M; ++j) {
scanf("%1d", &origin[i][j]);
}
}
for (int i=0; i<N; ++i) {
for (int j=0; j<M; ++j) {
scanf("%1d", &target[i][j]);
}
}
if (N<3 || M<3) {
if (isSame()) {
cout << 0;
return 0;
}
cout << -1;
return 0;
}
cout << change();
}