ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1463번
    백준알고리즘/DP알고리즘 2020. 10. 2. 21:54
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    
    int main()
    {
    	int dp[1000001];
    	int n;
    	cin >> n;
    	
    	dp[0] = 0;
    	dp[1] = 0;
    	for (int i = 2; i <= n; i++)
    	{
    		dp[i] = dp[i - 1] + 1;
    		if (i % 2 == 0)
    		{
    			dp[i] = min(dp[i], dp[i / 2] + 1);
    		}
    		if (i % 3 == 0)
    		{
    			dp[i] = min(dp[i], dp[i / 3] + 1);
    		}
    	}
    	cout << dp[n];
    }

     

    dp란 dynamic programming 으로써 동적 프로그래밍이다

     

    사람들은 dp란 문제를 해결할때 큰 틀에서 작은 틀로 좁혀가는것이 아닌 작은 문제부터 해결하여

    그 작은 문제를 기반으로 점점 큰 문제까지 해결해나가는 방법이라고한다.

     

    이  문제 또한 dp 방식으로 문제를 해결해나갔다.

     

    n이 주어졌을때 

     

    1.n-1

    2.n/2

    3.n/3

     

    이 세가지 방식을 활용하여 1까지 만들어 나갈때 계산식을 몇번 수행하면 1이 나오는지

    그리고

    그 수행 횟수가 가장 작은 수는 몇인지를 묻는 문제이다.

     

    자!

     

    먼저 n의 계산식 횟수를 구하기 전에 가장 작은 수 0 과 1 부터 몇번의 계산식을 수행해야 1이 나오는지 구해보자.

    고등학교를 졸업한 사람이라면 쉽게 해결할 수 있다.

     

    0과 같은경우 1이 될 수가 없다. 따라서 0번이다.

    1과 같은 경우 이미 1이 되어있기때문에 0번이다.

     

    이 횟수를 나는 dp라는 배열(테이블)에 저장해둘것이다.

     

    dp[0] = 0;

    dp[1] = 0;

     

    자 다음 n이 2가 되었을땐 어떻게 최소 계산식 수행 횟수를 구할 수 있을까?

    n이 2일땐 1을 만들기위해 2가지 방법이 있다.

     

    첫번째 방법

    2 - 1 = 1

     

    두번째 방법

    2/2 = 1

     

    이때 서두에서 주어진 3을 나누는 방식도 있지만 2는 3으로 나누어지지 않기때문에 건너뛴다.

     

    우리는 이제 첫번째 방법과 두번째 방법중 최소값을 구할것이다. 그리고 그 방식을 dp[2]에 저장할것이다.

     

    첫번째 방법의 횟수를 구하기 위한 식은 이렇게 된다.

    dp[2] = dp[i-1] + 1 이를 풀어보면 dp[2] = dp[1] + 1 이다.

     

    여기서 1을 왜 더하지? 라고 생각할 수 있다. 그 이유는 2에서 1을 뺌으로써 계산식 1번을 수행하기때문에

    1을 더하게된다.

     

    자 다시 식을 살펴보자

    dp[2] = dp[1] + 1이다.

    즉 2가 1이 되기 위해 수행해야하는 최소 계산식 수행 횟수는 dp[1] + 1이라는 소리이다. 

     

    여기서 

     

    dp[1]은 1이라는 숫자가 1이 되기 위한 최소 계산식 수행 횟수를 의미한다.

    우리는 dp[1] 의 값을 서두에서 미리 구해놓았다. 

     

    1이 1이 되기위해선 0번을 수행한다.. 이미 1이기때문이다.

    우리는 dp[1] + 1 식을 계산하여 dp[2] 즉 2가 1이 되기 위한 최소 계산식 수행 횟수를 구하게되었다. 

     

    다음으로 두번째 방법의 횟수를 구해보겠다.

     

    dp[2/2] + 1;

    2를 2로 나누면 1이된다.

    dp[1] + 1

    이 또한 갯수가 총 2개이다.

    첫번째 식과 두번째 식의 최소값을 구하려 했지만 둘다 2이기때문에

    dp[2] 에는 2를 저장해둔다.

     

    n이 3일때 또한 이런 방식으로 수행하여 최소값을 dp[3]에 저장해둔다. 

     

    계산식을 수행해보면 dp[3]에 1이 저장된다.

    다음 n이 4일때의 경우를 계산해보자.

     

    첫번째 경우

    dp[4] = dp[3] + 1;  dp[3]은 1이기때문에 dp[4] = 2가 주어진다.

    두번째 경우

    dp[4/2] + 1; dp[2]또한 1이기때문에 이 방법또한 값이 2이다.

     

    dp[4] = 2 저장

     

    n이 5일때

    첫번째 경우

    dp[5] = dp[4] + 1; dp[4]는 2이기때문에 dp[5] = 3이 주어진다. 2와 3으로 나눠지기않기때문에 다음으로 넘어간다.

     

    n이 6일때

    첫번째 경우

    dp[6] = dp[5] + 1 (dp[6] = 4)

     

    두번째 경우

    dp[6/2] + 1 (dp[3] + 1 = 2)

     

    세번째 경우

    dp[6/3] + 1 (dp[2] + 1 = 2)

     

    세가지 경우중 가장 작은 값은 총 2번 

     

    dp[6] = 2

     

    이런식으로 n의 최소 계산식 수행 횟수를 구하기 위해선 이전에 수행하여 구한 횟수들을 활용한다.

     

    이것이 바로 dp 방식이다. 

     

     

     

     

     

    '백준알고리즘 > DP알고리즘' 카테고리의 다른 글

    10844번  (0) 2020.10.03
    9095번  (0) 2020.10.03
    11727번  (0) 2020.10.03
    11726번  (0) 2020.10.03
Designed by Tistory.