[BOJ] 12852 "1로 만들기2" 문제 풀이 & 소스 코드 With C/C++

반응형
반응형

#INFO

난이도 :  SILVER1

알고리즘 유형 : DP

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

 

12852번: 1로 만들기 2

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 자연수 N이 주어진다.

www.acmicpc.net


#SOLVE

DynamicProgramming 방식을 이용해 문제를 풀이했습니다.

dp[i] = i 를 1로 만드는 연산의 최솟값

before[i] = 연산 (1 or 2 or 3) 을 수행하기 직전의 i 값 . ex) before[10] = 9

before 배열은 N을 1로 만드는 방법에 포함되어 있는 수를 출력하기 위해 정의했습니다.

 

1. X가 3으로 나누어 떨어지면 3으로 나눈다.

		before[i] = i - 1;
		if (i % 3 == 0 && dp[i] > dp[i/3] + 1) {
			dp[i] = dp[i/3] + 1;
			before[i] = i / 3;
		}

2. X가 2로 나누어 떨어지면 2로 나눈다.

		if (i % 2 == 0 && dp[i] > dp[i/2] + 1) {
			dp[i] = dp[i/2] + 1;
			before[i] = i / 2;
		}

3. 1을 뺀다.

		dp[i] = dp[i-1] + 1;
		before[i] = i - 1;

 

위의 3가지 식을 비교하며 최소로 연산을 수행하는 값을 dp 배열에 저장한 뒤 n번째 dp값을 출력하면 됩니다.


#CODE

#include <iostream>
using namespace std;

int dp[1000001];
int before[1000001];

int main() {
  	int n;
	cin >> n;
	
	//init
	dp[0] = 0;
	dp[1] = 0;
	before[1] = -1;
	
	//dp
	for(int i = 2 ; i <= n ; i++) {
		dp[i] = dp[i-1] + 1;
		before[i] = i - 1;
		if (i % 3 == 0 && dp[i] > dp[i/3] + 1) {
			dp[i] = dp[i/3] + 1;
			before[i] = i / 3;
		}
		if (i % 2 == 0 && dp[i] > dp[i/2] + 1) {
			dp[i] = dp[i/2] + 1;
			before[i] = i / 2;
		}
	}
	
	cout << dp[n] << endl;
	cout << n << " ";
	while(before[n] != -1) {
		cout << before[n] << " ";
		n = before[n];
	}
	return 0;
}
반응형

댓글

Designed by JB FACTORY