🖥️ CS/Baekjoon Algorithms

백준 1699번 제곱수의 합 (C++)

한국의 메타몽 2021. 4. 9. 15:26

문제 링크 : www.acmicpc.net/problem/1699

 

1699번: 제곱수의 합

어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다

www.acmicpc.net

문제 해석은 다음과 같다. 

1. 11을 제곱수로 나타내는 방법은 여러가지가 있는데, 대표 예시로 아래 두개를 봐보자.

11 = 3^2 + 1^2 + 1^2 (3개 항)

11 = 2^2 + 2^2 + 1^2 + 1^2 + 1^2 (5개 항)

2. 숫자 n이 주어졌을 때, n을 제곱수로 나타낼 수 있는 항의 최소 개수를 구하라.

 

문제 풀이는 다음과 같다. 

    for(int i=1; i<=n; i++){
        arr[i] = i;
        for(int j=1; j*j<=i; j++){
            if(arr[i]>arr[i-j*j]+1) arr[i] = arr[i-j*j]+1;
        }
    }

1. 이중 for문을 구현한다. 이때 첫 번째 for문의 최대 범위는 n까지이다.

2. 모든 숫자는 1의 제곱수 * 해당 숫자만큼의 갯수로 구현할 수 있이므로, arr[i] = i로 선정된다.

3. 두 번째 for문의 조건을 보자. j=1, j*j<=i인데, 어떤 숫자 i의 루트를 구한 값으로 제곱수를 구현할 수 있으므로 j*j<=i가 나오게 된다.

4. 우리의 목적은 제곱수의 최소 항을 구하는 것이다. 예를들어 n=4를 가정해보자.

 if(arr[i]>arr[i-j*j]+1) arr[i] = arr[i-j*j]+1;

arr[2] = 2이고, arr[4-2*2] = arr[0] = 0이다. arr[0]+1은 1인데, 여기서 +1이 붙은 이유는 4, 즉, 2의 제곱수인 4가 1개로 들어가기 때문이다. arr[4] = 4 보다 arr[4-2*2]+1 = 1이 더 작으므로, arr[4] = 1이 들어가게 된다.

 

#include <iostream>
#define MAX 100001
using namespace std;

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int n = 0, arr[MAX];
    cin >> n;
    for(int i=1; i<=n; i++){
        arr[i] = i;
        for(int j=1; j*j<=i; j++){
            if(arr[i]>arr[i-j*j]+1) arr[i] = arr[i-j*j]+1;
        }
    }
    cout << arr[n] << "\n";
    return 0;
}

 

'🖥️ CS > Baekjoon Algorithms' 카테고리의 다른 글

백준 11057번 오르막 수 (C++)  (0) 2021.04.10
백준 1309번 동물원 (C++)  (0) 2021.04.09
백준 18870번 좌표 압축 (C++)  (0) 2021.04.05
백준 1010번 다리 놓기 (C++)  (0) 2021.04.05
백준 2193번 이친수 (C++)  (0) 2021.04.05