문제 출처

1. 문제설명


  • 크기 3x3 배열에 값이 채워져있다.
  • R 연산과 C 연산이 있다.
    • R 연산: 배열 A의 모든 행에 대해서 정렬을 수행한다. 행의 개수 ≥ 열의 개수인 경우에 적용된다.
    • C 연산: 배열 A의 모든 열에 대해서 정렬을 수행한다. 행의 개수 < 열의 개수인 경우에 적용된다.
  • 예를 들어 다음과 같은 입력이 있다고 해보자

    1 2 3
    1 2 1
    2 1 3
    3 3 3
    
  • 이 입력은 다음 과정을 통해 총 2번 연산하게 된다.
    • 2번 연산하면 (1,2) 자리에 목표값 3이 존재하기 때문이다.
    1 2 1
    2 1 3
    3 3 3
      
    // 최근 결과 값이 행의 개수 == 열의 개수, 즉 R 연산
    2 1 1 2
    1 1 2 1 3 1
    3 3
      
    // 최근 결과 값이 최대 열의 개수는 6이고, 행은 3이므로 C연산
    1 3 1 1 3 1
    1 1 1 1 1 1
    2 1 2 2
    1 2 1 1
    3
    1
    
  • 다른 블로그보면 문제 설명하고 코드만 띡 올려놨는데,
  • 상세한 과정을 공유드리고 싶었다.

  • 문제 분류
    • Implementation, Sorting, Simulation


2. 알고리즘 설계


  • 값의 복사와 정렬 조건을 잘 명시해주면 된다.
  • 0은 정렬 과정에 들어가면 안되므로, 임시로 저장할 때는 0을 배제 시켜준다.

  • 재귀로 구현했고, 탈출 조건은 다음과 같다.

      if (A[r][c] == k) {  // 타겟값 만났을 때,
          t = cnt;
          return;
      }
      if (cnt > 100) {   // 100번 넘게 갱신될 때,
          t = -1;
          return;
      }
    
  • 처리 로직은 R연산, C연산의 차이가 거의 없다.
    • 가로축이냐 세로축이냐 정도의 차이
    • 내 구현에서는 세로축이 조금 더 복잡해 이걸 기준으로 설명하겠다.
    for (int i = 0; i < SZ; i++) {
          vector<int> tmp;
          for (int j = 0; j < SZ; j++) tmp.push_back(A[j][i]);  // 아래 get_cnt에 넣기 위해 값을 복사한다.
            
          vector<int> ret = get_cnt(tmp);  // 만약 가로축 배열을 넘긴다면 그냥 A[i]와 같이 넘기면 된다.
          for (int j = 0; j < ret.size(); j++) C[j][i] = ret[j];  // 정렬 기준에 따른 값과 개수 리스트를 임시 배열에 복사
    
          ymax = max(ymax, (int)ret.size());  // y축을 갱신해준다.
      }
    
    • 이후 원래 배열에 C 배열의 값을 복사해주면 된다.
  • 정렬
    • 연산자 오버로딩
    bool compare(pii &a, pii &b) {
      if (a.second == b.second) return a.first < b.first;
      return a.second < b.second;
    }
    
  • 개수 구하기
    • 값이 뭐가 들어있을지 모른다 100이하의 자연수… map을 써주도록 하자
    • map의 정렬을 위해 임시 벡터를 선언하고 값 복사 후 정렬
    • 값과 개수를 순차적으로 return할 벡터에 넣는다.
    • 원소의 값과 개수를 1차원 배열에 저장해 값을 그대로 붙여넣는 방식의 구현이다.
    vector<int> get_cnt(vector<int> &v) {
      map<int, int> mp;
        
      for (int i = 0; i < v.size(); i++) {
          if (v[i] == 0) continue;
          mp[v[i]]++;
      }
    
      vector<pii> tmp(mp.begin(), mp.end());
      sort(tmp.begin(), tmp.end(), compare);
    
      vector<int> ret;
      for (pii nxt : tmp) {
          ret.push_back(nxt.first);
          ret.push_back(nxt.second);
      }
    
      return ret;
    }
    


3. 전체 코드


#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;

const int SZ = 100;
int r, c, k, t = -1;
vector<int> A[SZ], C[SZ];

bool compare(pii &a, pii &b) {
    if (a.second == b.second) return a.first < b.first;
    return a.second < b.second;
}

vector<int> get_cnt(vector<int> &v) {
    map<int, int> mp;
    
    for (int i = 0; i < v.size(); i++) {
        if (v[i] == 0) continue;
        mp[v[i]]++;
    }

    vector<pii> tmp(mp.begin(), mp.end());
    sort(tmp.begin(), tmp.end(), compare);

    vector<int> ret;
    for (pii nxt : tmp) {
        ret.push_back(nxt.first);
        ret.push_back(nxt.second);
    }

    return ret;
}

void solve(int cnt, int ymax, int xmax) {
    if (t != -1) return;
    if (A[r][c] == k) {
        t = cnt;
        return;
    }
    if (cnt > 100) {
        t = -1;
        return;
    }

    for (int i = 0; i < SZ; i++) {
        C[i].clear();
        C[i].assign(100, 0);
    }

    if (ymax >= xmax) {
        for (int i = 0; i < SZ; i++) {
            vector<int> ret = get_cnt(A[i]);
            for (int j = 0; j < ret.size(); j++) C[i][j] = ret[j];

            xmax = max(xmax, (int)ret.size());
        }
    }
    else {
        for (int i = 0; i < SZ; i++) {
            vector<int> tmp;
            for (int j = 0; j < SZ; j++) tmp.push_back(A[j][i]);
            
            vector<int> ret = get_cnt(tmp);
            for (int j = 0; j < ret.size(); j++) C[j][i] = ret[j];

            ymax = max(ymax, (int)ret.size());
        }
    }

    for (int i = 0; i < SZ; i++)
        for (int j = 0; j < SZ; j++)
            A[i][j] = C[i][j];

    solve(cnt + 1, ymax, xmax);

    return;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    for(int i=0; i<SZ; i++)
        A[i].assign(100, 0);

    cin >> r >> c >> k;
    for (int a, b, c, i = 0; i < 3; i++)
        cin >> A[i][0] >> A[i][1] >> A[i][2];

    r--, c--;

    solve(0, 3, 3);

    cout << t;
    return 0;
}