사고쳤어요
[백준] 17140 이차원 배열과 계산 (C++) 본문
링크: https://www.acmicpc.net/problem/17140
문제
크기가 3×3인 배열 A가 있다. 배열의 인덱스는 1부터 시작한다. 1초가 지날때마다 배열에 연산이 적용된다.
- R 연산: 배열 A의 모든 행에 대해서 정렬을 수행한다. 행의 개수 ≥ 열의 개수인 경우에 적용된다.
- C 연산: 배열 A의 모든 열에 대해서 정렬을 수행한다. 행의 개수 < 열의 개수인 경우에 적용된다.
한 행 또는 열에 있는 수를 정렬하려면, 각각의 수가 몇 번 나왔는지 알아야 한다. 그 다음, 수의 등장 횟수가 커지는 순으로, 그러한 것이 여러가지면 수가 커지는 순으로 정렬한다. 그 다음에는 배열 A에 정렬된 결과를 다시 넣어야 한다. 정렬된 결과를 배열에 넣을 때는, 수와 등장 횟수를 모두 넣으며, 순서는 수가 먼저이다.
예를 들어, [3, 1, 1]에는 3이 1번, 1가 2번 등장한다. 따라서, 정렬된 결과는 [3, 1, 1, 2]가 된다. 다시 이 배열에는 3이 1번, 1이 2번, 2가 1번 등장한다. 다시 정렬하면 [2, 1, 3, 1, 1, 2]가 된다.
정렬된 결과를 배열에 다시 넣으면 행 또는 열의 크기가 달라질 수 있다. R 연산이 적용된 경우에는 가장 큰 행을 기준으로 모든 행의 크기가 변하고, C 연산이 적용된 경우에는 가장 큰 열을 기준으로 모든 열의 크기가 변한다. 행 또는 열의 크기가 커진 곳에는 0이 채워진다. 수를 정렬할 때 0은 무시해야 한다. 예를 들어, [3, 2, 0, 0]을 정렬한 결과는 [3, 2]를 정렬한 결과와 같다.
행 또는 열의 크기가 100을 넘어가는 경우에는 처음 100개를 제외한 나머지는 버린다.
배열 A에 들어있는 수와 r, c, k가 주어졌을 때, A[r][c]에 들어있는 값이 k가 되기 위한 최소 시간을 구해보자.
입력
첫째 줄에 r, c, k가 주어진다. (1 ≤ r, c, k ≤ 100)
둘째 줄부터 3개의 줄에 배열 A에 들어있는 수가 주어진다. 배열 A에 들어있는 수는 100보다 작거나 같은 자연수이다.
출력
A[r][c]에 들어있는 값이 k가 되기 위한 연산의 최소 시간을 출력한다. 100초가 지나도 A[r][c] = k가 되지 않으면 -1을 출력한다.
풀이
매우 열정적으로 구현을 해야 하는 문제이다.
예를 들어 모든 행에 대해서 정렬을 수행할 경우, 행에서 등장하는 숫자 1, 2, 3...의 등장 횟수를 세야 한다.
예를 들어 1이 2번, 2가 1번, 3가 2번 등장하였을 경우 {1, 2}, {2, 1}, {3, 2}와 같이 묶을 수 있고
등장 횟수가 커지는 순으로, 등장 횟수가 같다면 수가 커지는 순으로 위를 정렬하면
{2, 1}, {1, 2}, {3, 2} → {2, 1, 1, 2, 3, 2}와 같이 정렬될 것이다.
C++에서는 vector<pair<int, int>>를 정렬할 경우 그 안의 pair<int, int>의 first와 second를 고려하여 정렬해주기 때문에이를 활용하면 쉽게 정렬할 수 있다.
코드
#include <iostream>
#include <vector>
#include <map>
#include <climits>
#include <algorithm>
#define MAX INT_MAX
using namespace std;
int arr[200][200];
int rows = 3;
int columns = 3;
void solve(){
int maxI, maxJ;
bool isRow = true;
vector<vector<int>> newArr;
// R 연산
if (rows >= columns){
for (int i = 1; i <= rows; i++){
map<int, int> numCnt;
vector<pair<int, int>> vec;
// 조건에 맞게 vec에 넣기
for (int j = 1; j <= columns; j++){
if (arr[i][j]){ // 0은 정렬에 포함되지 않음
numCnt[arr[i][j]]++;
}
}
for (auto it = numCnt.begin(); it != numCnt.end(); it++){
int key = it->first;
int val = it->second;
vec.push_back({val, key}); // {등장횟수, 수}
}
// 정렬
sort(vec.begin(), vec.end());
// 정렬한 값을 newArr에 1차로 넣음
newArr.push_back({});
for (int j = 1; j <= vec.size(); j++){
newArr[i-1].push_back(vec[j-1].second);
newArr[i-1].push_back(vec[j-1].first);
}
//
int size = vec.size() * 2;
columns = max(columns, size);
}
// newArr 값을 arr로 업데이트
for (int i = 1; i <= rows; i++){
for (int j = 1; j <= newArr[i-1].size(); j++){
arr[i][j] = newArr[i-1][j-1];
}
for (int j = newArr[i-1].size()+1; j <= columns; j++){
arr[i][j] = 0; // 0 채워넣기
}
}
}
// C 연산
else{
for (int i = 1; i <= columns; i++){
map<int, int> numCnt;
vector<pair<int, int>> vec;
// 조건에 맞게 vec에 넣기
for (int j = 1; j <= rows; j++){
if (arr[j][i]){ // 0은 정렬에 포함되지 않음
numCnt[arr[j][i]]++;
}
}
for (auto it = numCnt.begin(); it != numCnt.end(); it++){
int key = it->first;
int val = it->second;
vec.push_back({val, key}); // {등장횟수, 수}
}
// 정렬
sort(vec.begin(), vec.end());
// 정렬한 값을 newArr에 1차로 넣음
newArr.push_back({});
for (int j = 1; j <= vec.size(); j++){
newArr[i-1].push_back(vec[j-1].second);
newArr[i-1].push_back(vec[j-1].first);
}
int size = vec.size() * 2;
rows = max(rows, size);
}
// newArr 값을 arr로 업데이트
for (int i = 1; i <= columns; i++){
for (int j = 1; j <= newArr[i-1].size(); j++){
arr[j][i] = newArr[i-1][j-1];
}
for (int j = newArr[i-1].size()+1; j <= rows; j++){
arr[j][i] = 0; // 0 채워넣기
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int r, c, k;
cin >> r >> c >> k;
for (int i = 1; i <= 3; i++){
for (int j = 1; j <= 3; j++){
cin >> arr[i][j];
}
}
int cnt = 0;
while (cnt <= 100 && arr[r][c] != k){
solve();
cnt++;
}
if (cnt > 100){
cout << -1;
}
else{
cout << cnt;
}
}

'백준 > Gold' 카테고리의 다른 글
| [백준] 13144 List of Unique Numbers (C++) (0) | 2025.11.03 |
|---|---|
| [백준] 1562 계단 수 (C++) (0) | 2025.09.23 |
| [백준] 2213 트리의 독립집합 (C++) (0) | 2025.02.17 |
| [백준] 1327 소트게임 (C++) (0) | 2024.11.11 |
| [백준] 1826 연료 채우기 (C++) (1) | 2024.11.08 |