πŸ•οΈ ICPC Sinchon/Dynamic Programming

[BOJ][C++] λ°±μ€€ 1699번: 제곱수의 ν•©

선달 2024. 8. 14. 03:45
λ°˜μ‘ν˜•

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

 

문제

μ–΄λ–€ μžμ—°μˆ˜ N은 그보닀 μž‘κ±°λ‚˜ 같은 μ œκ³±μˆ˜λ“€μ˜ ν•©μœΌλ‘œ λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄ 11=32+12+12(3개 ν•­)이닀. 이런 ν‘œν˜„λ°©λ²•μ€ μ—¬λŸ¬ 가지가 될 수 μžˆλŠ”λ°, 11의 경우 11=22+22+12+12+12(5개 ν•­)도 κ°€λŠ₯ν•˜λ‹€. 이 경우, μˆ˜ν•™μž μˆŒν¬λΌν…ŒμŠ€λŠ” “11은 3개 ν•­μ˜ 제곱수 ν•©μœΌλ‘œ ν‘œν˜„ν•  수 μžˆλ‹€.”라고 λ§ν•œλ‹€. λ˜ν•œ 11은 그보닀 적은 ν•­μ˜ 제곱수 ν•©μœΌλ‘œ ν‘œν˜„ν•  수 μ—†μœΌλ―€λ‘œ, 11을 κ·Έ ν•©μœΌλ‘œμ¨ ν‘œν˜„ν•  수 μžˆλŠ” 제곱수 ν•­μ˜ μ΅œμ†Œ κ°œμˆ˜λŠ” 3이닀.

주어진 μžμ—°μˆ˜ N을 μ΄λ ‡κ²Œ μ œκ³±μˆ˜λ“€μ˜ ν•©μœΌλ‘œ ν‘œν˜„ν•  λ•Œμ— κ·Έ ν•­μ˜ μ΅œμ†Œκ°œμˆ˜λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯

첫째 쀄에 μžμ—°μˆ˜ N이 주어진닀. (1 ≤ N ≤ 100,000)

좜λ ₯

주어진 μžμ—°μˆ˜λ₯Ό 제곱수의 ν•©μœΌλ‘œ λ‚˜νƒ€λ‚Ό λ•Œμ— κ·Έ 제곱수 ν•­μ˜ μ΅œμ†Œ 개수λ₯Ό 좜λ ₯ν•œλ‹€.

 

풀이

dp[i] = 숫자 i의 제곱수 ν•­μ˜ μ΅œμ†Œ 갯수

 

숫자 n이 μ£Όμ–΄μ‘Œμ„ λ•Œ,

  • n = 1 + dp[n-1]의 μ „κ°œ
  • n = 4 + dp[n-4]의 μ „κ°œ
  • n = 9 + dp[n-9]의 μ „κ°œ
  • n = 16 + dp[n-16]의 μ „κ°œ

...

이런 ν˜•νƒœλ‘œ λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€.

 

예λ₯Ό λ“€μ–΄ n=10이라면

  • 10 = 9 + dp[10-9]의 μ „κ°œ = 9 + dp[1]의 μ „κ°œ = 9 + (1)
    => ν•­ 갯수 1+dp[1] = 2개 
  • 10 = 4 + dp[10-4]의 μ „κ°œ = 4 + dp[6]의 μ „κ°œ = 4 + (4+1+1)
    => ν•­ 갯수 1+dp[6] = 4개
  • 10 = 1 + dp[10-9]의 μ „κ°œ = 1 + dp[9]의 μ „κ°œ = 1 + (9)
    => ν•­ 갯수 1+dp[9] = 2개 

라고 ν•  수 μžˆλ‹€

 

즉 dp[1]~dp[n]의 κ°’λ§Œ μžˆλ‹€λ©΄ dp[n+1]의 값을 ꡬ할 수 μžˆλ‹€.

nμ—μ„œ 제곱수λ₯Ό λΉΌμ£Όκ³  남은 κ°’μ˜ μ œκ³±μˆ˜ν•­ κ°―μˆ˜μ— 1을 λ”ν•œ 값이 n의 μ œκ³±μˆ˜ν•­ 갯수 μ΄λ―€λ‘œ

n보닀 μž‘μ€ μ œκ³±μˆ˜λ“€μ„ 반볡문으둜 λΉΌμ„œ 계산해주고 μ΅œμ†Œκ°’μ„ κ΅¬ν•΄μ„œ dp에 μ €μž₯ν•΄μ£Όλ©΄ 끝 !

 

// 풀이 : https://whkakrkr.tistory.com

#include <iostream>
#include <vector>

using namespace std;

const int INF = 100001;

int main() {
    int n;
    cin >> n;
    
    vector<int>dp(INF);
    dp[0] = 0;
    dp[1] = 1;
    for(int i=2; i<INF; i++) {
        int min_val = i;
        for(int j=1; j*j<=i; j++) {
            int cur = i - j*j;
            if(min_val > dp[cur]) {
                min_val = dp[cur];
            }
        }
        dp[i] = min_val+1;
    }

    cout << dp[n] << "\n";
    
    return 0;
}
λ°˜μ‘ν˜•