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




풀이


dp를 이용해서 풀기로 한다. N의 범위가 100,000이므로 100,000의 제곱근의 반올림 수인 317개의 배열을 선언해 주기로한다.

dp[100001] = { 0 };

arr[317]  = { 0 };

그리고 dp 배열을 모두 -1로 초기화 해주기로 한다. 그 이유는 0과 -1의 구분을 짓기 위해서인데 초기화 했던 -1로 계속 값이 남아 있는 경우는 이전까지의 

제곱수로 만들수 없다는 것을 의미하게끔 하기 위해 


또, dp[0]값과 초기화 값이 0으로 동일하다면 min함수를 쓰기가 어려워지기 때문에 if(dp == -1) 조건을 두어

사전에 거르기 위함이다.


dp[0] = 0개

dp[1] =   1개    /     1^2 

dp[2] =  2개    /   1^2 + 1^2 

dp[3] =   3개    /    1^2 + 1^2 + 1^2

dp[4] =    1개    /    min(dp[3] + 1개(1^2) or  dp[0] + 1개(2^2))

dp[5] =    2개   /    dp[4] + 1개(1^2)    

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

dp[7] =     4개    /    dp[6] + 1개(1^2)

dp[8] =    2개    /    min(dp[7]    or   dp[4]  + 1개(2^2))

.

.

.

이런식으로 비교해주면서 최소값을 저장해 나가면 된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
 
#define min(a,b) a<b ? a:b
 
int main() {
    int N;
    int cnt = 1;
    int arr[317= { 0 };
    int dp[100001];
 
    memset(dp, -1sizeof(dp));
    
    scanf("%d"&N);
    for (int i = 1; i <= (int) sqrt(N); i++) {
        arr[i] = cnt*cnt;
        cnt++;
    }
 
    
    dp[0= 0;
    
    for (int i = 1; i <= N; i++) {
        for (int j=1; j <= (int) sqrt(i); j++) {
            if (i >= arr[j] && dp[i - arr[j]] != -1) {
                if (dp[i] == -1) dp[i] = dp[i - arr[j]] + 1;
                else dp[i] = min(dp[i], dp[i - arr[j]] + 1);
            }
        }
    }
 
    printf("%d\n", dp[N]);
    
    return 0;
}
cs


'알고리즘' 카테고리의 다른 글

(11055)(DP) 백준 가장 큰 증가 부분 수열  (0) 2018.08.07
(2133)(DP) 백준 타일 채우기  (2) 2018.08.06
(11048)(DP) 백준 이동하기  (0) 2018.08.01
(2294)(DP) 백준 동전2  (0) 2018.08.01
(11057)(DP) 백준 오르막 수  (0) 2018.07.30

+ Recent posts