🙇‍♀️[Gold IV] 이차원 배열과 연산 - 17140

문제 링크

성능 요약

메모리: 2156 KB, 시간: 8 ms

분류

구현, 시뮬레이션, 정렬

제출 일자

2024년 3월 13일 19:02:19

문제 설명

크기가 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을 출력한다.

🚀풀이

R연산과 C연산을 할 때 정렬을 특수하게 하므로 그에 맞는 구조체를 만들었다.

struct Num
{
	int num, cnt;
	bool operator<(const Num& other)
	{
		if (cnt == other.cnt)
			return num < other.num;
		else
			return cnt < other.cnt;
	}
};

숫자와 숫자가 나온 개수를 담고있다.

로직은 Num을 담는 새로운 벡터를 만들고, 그곳에 숫자와 숫자의 개수를 카운트 해준다.

그 뒤 Num벡터를 정렬하고 정렬된 값에 맞춰서 기존 배열을 갱신한다.

전역변수와 R,C함수는 다음과 같다.
주석으로 각 설명을 더했다.

int r, c, k;
int r_len = 3, c_len = 3;
vector<vector<int>> board;
vector<Num> numbers;

void R()
{
	// 각 수가 얼만큼 나왔는지 알아야한다.
	int max_r_len = 0;
	int max_c_len = 0; // 이게 갱신됨.
	for (int y = 1; y <= r_len; ++y)
	{
		numbers.clear();
		numbers.resize(101);
        // 인덱스가 각 숫자랑 동일하게 만들기.
		for (int i = 1; i <= 100; ++i)
			numbers[i].num = i;

        // 배열의 숫자 카운팅.
		for (int x = 1; x <= c_len; ++x)
		{
			numbers[board[y][x]].cnt++;
		}
        // 카운트가 다 됐으므로 정렬.
		sort(numbers.begin(), numbers.end());

        // 기존 배열 비우기.
		board[y].clear();
        // 1부터 시작하니까 0값을 삽입.
		board[y].push_back(0);
        // 길이 계산용.
		int len = 0;
		for (int i = 1; i <= 100; ++i)
		{
            // 숫자가 0이거나 카운트가 0이라면 스킵.
			if (numbers[i].cnt == 0 || numbers[i].num == 0)
				continue;
            // 숫자부터 삽입.
			board[y].push_back(numbers[i].num);
			len++;
            // 개수 삽입.
			board[y].push_back(numbers[i].cnt);
			len++;
		}
        // 나머지는 0으로 채워주기.
		for (int i = len; i <= 100; ++i)
			board[y].push_back(0);

		max_c_len = max(max_c_len, len);
	}

	c_len = max(c_len, max_c_len);
}

void C()
{
	int max_r_len = 0;
	int max_c_len = 0;
	for (int x = 1; x <= c_len; ++x)
	{
		numbers.clear();
		numbers.resize(101);
		for (int i = 1; i <= 100; ++i)
			numbers[i].num = i;

		for (int y = 1; y <= r_len; ++y)
		{
			numbers[board[y][x]].cnt++;
		}
		sort(numbers.begin(), numbers.end());
		board[0][x] = 0;
		int len = 0;
		int idx = 1;
		for (int i = 1; i <= 100; ++i)
		{
			if (numbers[i].cnt == 0 || numbers[i].num == 0)
				continue;
			board[idx][x] = numbers[i].num;
			idx++;
			len++;
			board[idx][x] = numbers[i].cnt;
			idx++;
			len++;
		}
		max_r_len = max(max_r_len, len);
		for (int i = len + 1; i <= 100; ++i)
		{
			board[i][x] = 0;
		}

	}

	r_len = max(r_len, max_r_len);

}

solve함수는 다음과 같다.

void solve()
{
	// 입력값 받기.
	cin >> r >> c >> k;
	board = vector<vector<int>>(101, vector<int>(101));
	for (int y = 1; y <= 3; ++y)
	{
		for (int x = 1; x <= 3; ++x)
		{
			cin >> board[y][x];
		}
	}

	for (int i = 0; i <= 101; ++i)
	{
        // 100초를 넘겼을 경우.
		if (i == 101)
		{
			cout << -1;
			break;
		}
        // 정답을 찾았을 경우.
		if (board[r][c] == k)
		{
			cout << i;
			break;
		}

		if (r_len >= c_len)
			R();
		else
			C();
	}
}

image

🚀전체 코드

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include<iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <math.h>

using namespace std;

struct Num
{
	int num, cnt;
	bool operator<(const Num& other)
	{
		if (cnt == other.cnt)
			return num < other.num;
		else
			return cnt < other.cnt;
	}
};

int r, c, k, total_time = 0;
int r_len = 3, c_len = 3;
vector<vector<int>> board;
vector<Num> numbers;

void R()
{
	// 각 수가 얼만큼 나왔는지 알아야한다.
	int max_r_len = 0;
	int max_c_len = 0; // 이게 갱신됨.
	for (int y = 1; y <= r_len; ++y)
	{
		numbers.clear();
		numbers.resize(101);
		for (int i = 1; i <= 100; ++i)
			numbers[i].num = i;

		for (int x = 1; x <= c_len; ++x)
		{
			numbers[board[y][x]].cnt++;
		}
		sort(numbers.begin(), numbers.end());

		board[y].clear();
		board[y].push_back(0);
		int len = 0;
		for (int i = 1; i <= 100; ++i)
		{
			if (numbers[i].cnt == 0 || numbers[i].num == 0)
				continue;
			board[y].push_back(numbers[i].num);
			len++;
			board[y].push_back(numbers[i].cnt);
			len++;
		}
		for (int i = len; i <= 100; ++i)
			board[y].push_back(0);

		max_c_len = max(max_c_len, len);
	}

	c_len = max(c_len, max_c_len);
}

void C()
{
	int max_r_len = 0;
	int max_c_len = 0;
	for (int x = 1; x <= c_len; ++x)
	{
		numbers.clear();
		numbers.resize(101);
		for (int i = 1; i <= 100; ++i)
			numbers[i].num = i;

		for (int y = 1; y <= r_len; ++y)
		{
			numbers[board[y][x]].cnt++;
		}
		sort(numbers.begin(), numbers.end());
		board[0][x] = 0;
		int len = 0;
		int idx = 1;
		for (int i = 1; i <= 100; ++i)
		{
			if (numbers[i].cnt == 0 || numbers[i].num == 0)
				continue;
			board[idx][x] = numbers[i].num;
			idx++;
			len++;
			board[idx][x] = numbers[i].cnt;
			idx++;
			len++;
		}
		max_r_len = max(max_r_len, len);
		for (int i = len + 1; i <= 100; ++i)
		{
			board[i][x] = 0;
		}

	}

	r_len = max(r_len, max_r_len);

}

void solve()
{
	// 입력값 받기.
	cin >> r >> c >> k;
	board = vector<vector<int>>(101, vector<int>(101));
	for (int y = 1; y <= 3; ++y)
	{
		for (int x = 1; x <= 3; ++x)
		{
			cin >> board[y][x];
		}
	}

	for (int i = 0; i <= 101; ++i)
	{
		if (i == 101)
		{
			cout << -1;
			break;
		}
		if (board[r][c] == k)
		{
			cout << i;
			break;
		}

		if (r_len >= c_len)
			R();
		else
			C();
	}
}

int main() 
{
	FILE* stream;
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	freopen_s(&stream, "input.txt", "rt", stdin);

	solve();

	return 0;
}