본문 바로가기

BOJ 문제풀이

#1080 행렬

2022-05-22

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

 

1080번: 행렬

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

www.acmicpc.net

실버 1의 문제이다. 문제는 굉장히 단순한데에 비해 난이도는 좀 높았던 것 같다. 행렬 뒤집는거를 어떻게 할지 고민하다가 지쳐서 답안 코드를 보고서야 해결했다 ㅠㅠ.

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int n,m;
int mata[51][51];
int matb[51][51];

void matrixChange(int x,int y){
  for(int i=x;i<=x+2;i++){
    for(int j=y;j<=y+2;j++){
      mata[i][j]=1-mata[i][j];
    }
  }
}

int main()
{
  freopen("input.txt","r",stdin);
  cin>>n>>m;
  int cnt=0;
  
  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      scanf("%1d",&mata[i][j]);
    }
  }
  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      scanf("%1d",&matb[i][j]);
    }
  }

  for(int i=0;i<=n-3;i++){
    for(int j=0;j<=m-3;j++){
      if(mata[i][j]!=matb[i][j]){
        matrixChange(i,j);
        cnt++;
      }
    }
  }

  bool flag=false;
  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      if(mata[i][j]!=matb[i][j]){
        cnt=-1;
        flag=true;
        break;
      }
    }
    if(flag==true)
      break;
  }
  cout<<cnt;
}

일단 빈칸없이 주어지는 입력을 하나씩 받기 위해 필요한 scanf("%1d",&~~) 는 꼭 외워둬야 할 것 같다. 물론 문자열로 입력 받은다음에 아스키코드를 이용해서 숫자로 바꿀 수는 있지만 이 방법이 훨씬 간단하고 좋은 것 같다.

행렬은 3*3의 크기 단위로만 뒤집을 수 있으므로, 먼저 3*3이 언제까지 되는지를 알아야했다. 생각해보니 행은 N-3까지, 열은 M-3 까지 가능했다. 

 

이중 for문을 돌리면서 a와 b가 다른점이 있다면 3*3크기만큼 뒤집어 주었다. 이 과정을 (0,0) 부터 (N-3,M-3) 까지 반복 했다. 이렇게 다 뒤집고 난 뒤에 만들어진 a와 b를 비교해서 모든점이 같다면 cnt변수를 출력해주었고, 하나라도 다른점이 있다면 a에서 b로 바뀔수 없다는 것이기 때문에 -1을 cnt에 대입해주고 break 를 해주었다.

 

항상 해결하고나면 그렇게까지 어렵지 않은거 같은데 풀기전에는 너무 어렵게 느껴진다 ㅠ.

 

'BOJ 문제풀이' 카테고리의 다른 글

#2225 합분해  (0) 2022.05.22
#9465 스티커  (0) 2022.05.22
#2012 등수 매기기  (0) 2022.05.21
#1789 수들의 합  (0) 2022.05.21
#18310 안테나  (0) 2022.05.21