1 분 소요

크게 만들기 (백준 Gold 3)

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

N자리 숫자가 주어졌을때,
숫자 K개를 지워 얻을 수 있는 가장 큰 수를 구하는 문제
(k는 n보다 작음)

풀이 방법

당연한 얘기지만
기본적인 자릿수는 N-K가 될 것이고
결국 ‘맨’ 앞에 N-K까지의 가능한 ‘큰 수’가 도달해야 가장 클 것이다

(1924에서 2를 지운다고 했을때, 적어도 9가 맨 앞자리에 있어야 가장 클것이므로)

그렇기에 결과용 string에 현재 값을 ‘담은 후’
그 다음값과 비교하여 ‘작다면’ k를 소모하여

앞 자리를 제거하는 방식을 취하였다

그런 방식으로 문자열을 순회 후
k가 남았다면 뒷수부터 제거하는 방식으로 문제를 풀었다

ex)
4177252841 라는 숫자가 있고 K가 8이상이라면
앞의 숫자들을 최대한 제거하고 가장 큰 수인 ‘8’까지 도달하는 것이 목표일 것
(반대로 8을 지우지 않은 경우, 최대 숫자를 만들 수 없음)

  • 그렇기에 결과 string의 ‘가장 뒤’와
    현재 비교 문자 c 를 비교함에 따라
    ‘가장 뒤’에서 pop_back 하는 부분은
    stack 자료구조를 고려할 수 있다
    (다만 stl 컨테이너들 중 string은 이미 pop_back과 push_back이
    존재하기에 별도로 stack을 사용하진 않았음)

  • 또한 ‘현재’ 작은 문제들에서 ‘최선’값을 찾는 것이
    전체적인 최선 값을 찾는 방식이므로
    ‘그리디 알고리즘’이라 표현할 수 있다

제출 코드

#include<iostream>
#include<string>

using namespace std;

int main()
{
	int n, k;
	cin >> n >> k;

	string str;
	cin >> str;

	string ret = "";
	ret.push_back(str[0]);

	for (int i = 1; i < n; i++)
	{
		// c를 지워가면서 이전 ret의 back 부분과 비교하기
		char c = str[i];

		while (ret.empty() == false)
		{
			if (k > 0 && c > ret.back())
			{
				k--;
				ret.pop_back();
			}
			else
				break;
		}

		ret.push_back(c);
	}

	while (k > 0)
	{
		k--;
		ret.pop_back();
	}

	cout << ret;
}

결과

Image

일부 틀린 부분은 마지막 while 문에서
k– 를 빼뜨려 발생한 문제였다…

댓글남기기