BOJ 17140. 이차원 배열과 연산
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; }