λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

Algorithm/BOJ

[BOJ] 제곱수의 ν•©(1699)

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

문제 : BOJ_1699번 제곱수의 ν•©

문제 μ„€λͺ…

DP

DP둜 ν’€ 수 μžˆλŠ” 기본문제 동전 2와 μœ μ‚¬ν•œ 제곱수의 ν•© λ¬Έμ œμž…λ‹ˆλ‹€.
1λΆ€ν„° 10λ§ŒκΉŒμ§€μ˜ 수 쀑 ν•˜λ‚˜κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, κ·Έ 수λ₯Ό 제곱수둜 ν‘œν˜„ν•  수 μžˆλŠ” μ΅œμ†Œν•­ 개수λ₯Ό κ΅¬ν•˜λŠ” λ¬Έμ œμž…λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, 11의 κ²½μš°μ—” 11 = 2^2 + 2^2 + 1^2 + 1^2 + 1^2 5개 항도 κ°€λŠ₯ν•©λ‹ˆλ‹€.
ν•˜μ§€λ§Œ, 11 = 3^2 + 1^2 + 1^2 의 3κ°œν•­μœΌλ‘œλ„ ν‘œν˜„μ΄ κ°€λŠ₯ν•˜λ―€λ‘œ 11이 주어지면 3을 좜λ ₯ν•΄μ•Ό ν•©λ‹ˆλ‹€.


Solution

ν•­μ˜ 개수λ₯Ό μ΅œμ†Œν•œμœΌλ‘œ μ“°κΈ° μœ„ν•΄ 처음 ν–ˆλ˜ 생각은, λ‹¨μˆœν•˜κ²Œ 주어진 μˆ˜μ™€ μ΅œλŒ€ν•œ κ°€κΉŒμš΄ 제곱수λ₯Ό κ΅¬ν•˜λŠ” κ²ƒμ΄μ—ˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, 145λ©΄ 12^2, 100이면 9^2κ³Ό 같이 κ°€μž₯ κ°€κΉŒμš΄ 수λ₯Ό 찾은 λ’€,

dp[주어진 수] = dp[κ°€κΉŒμš΄ 수] - dp[주어진 수 - κ°€κΉŒμš΄ 수]

둜 ν•΄κ²°ν•˜λ € ν–ˆμ§€λ§Œ, 무쑰건 κ°€κΉŒμš΄ 수만 μ“°λ©΄ 였히렀 ν•­μ˜ μˆ˜κ°€ λŠ˜μ–΄λ‚˜λŠ” λ°˜λ‘€κ°€ μžˆμ—ˆκΈ° λ•Œλ¬Έμ— 이 방법은 ν‹€λ ΈμŠ΅λ‹ˆλ‹€.

κ²°κ΅­ λ¬Έμ œλŠ” μ œκ³±μˆ˜λ“€λ§Œ μ΄μš©ν•΄μ„œ dpλ₯Ό λŒλ €μ•Ό ν•˜λŠ” 게 핡심인데, μ΄λ•Œ 주어진 μˆ˜μ™€ κ°€μž₯ κ°€κΉŒμš΄ 제곱수만 λŒλ¦¬λŠ” 것이 μ•„λ‹Œ 주어진 수 보닀 μž‘μ€ 제곱수라면 계속 μ΅œμ†Ÿκ°’μ„ 확인해 μ£ΌλŠ” 게 λ°©λ²•μž…λ‹ˆλ‹€.

λ˜ν•œ, dp 값을 확인해야 ν•˜λŠ” μˆ˜κ°€ 제곱수라면 dp[확인해야 ν•˜λŠ” 수] = 1;둜 κ°±μ‹ ν•΄ μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

for 문으둜 1λΆ€ν„° ꡬ해야 ν•˜λŠ” 값보닀 μž‘μ€ 제곱수의 κ°’κΉŒμ§€

dp[κ°’] = min(dp[κ°’], (dp[κ°’ - 제곱수의 κ°’] + dp[제곱수의 κ°’]));

으둜 ν•΄λ‹Ή κ°’μ˜ μ΅œμ†Ÿκ°’μ„ 계속 κ°±μ‹ ν•΄ μ€λ‹ˆλ‹€.


Description

  • μ΅œμ†Ÿκ°’μ„ κ°±μ‹ ν•˜κΈ° μ „ λͺ¨λ‘ INF κ°’μœΌλ‘œ dp 값을 μ΄ˆκΈ°ν™”ν•΄μ€λ‹ˆλ‹€.
  • N이 μ΅œλŒ€ 100,000μ΄λ―€λ‘œ, 100,001을 INF둜 μ •ν–ˆμŠ΅λ‹ˆλ‹€.
  • sqrt()λ₯Ό μ΄μš©ν•΄μ„œ ν•΄λ‹Ή 값이 μ œκ³±μˆ˜μΈμ§€λ₯Ό 확인해 μ£Όκ³  제곱수 배열에 λ„£μ–΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#define INF 100001
using namespace std;
int main(void) {
    int N;
    cin >> N;
    vector<int> dp(N + 1);
    for (int i = 0; i <= N; i++) dp[i] = INF;
    vector<int> value;
    for (int i = 1; i * i < N; i++) {
        value.push_back(i * i);
    }
    dp[1] = 1;
    int size = value.size();
    for (int i = 2; i <= N; i++) {
        int chk = sqrt(i);
        if (chk * chk == i) {
            dp[i] = 1;
            continue;
        }
        for (int j = 0; j < size; j++) {
            if (value[j] > i) break;
            dp[i] = min(dp[i], dp[i - value[j]] + dp[value[j]]);
        }
    }
    cout << dp[N] << '\n';
    return 0;
}

'Algorithm > BOJ' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[BOJ] νšŒμ „ν•˜λŠ” 큐(1021)  (0) 2022.03.10
[BOJ] 였λ₯΄λ§‰ 수(11057)  (0) 2022.03.09
[BOJ] 동전 2(2294)  (0) 2022.03.09
[BOJ] 2xn 타일링(11726)  (0) 2022.03.09
[BOJ] μš©λŸ‰ λΆ€μ‘±(5446)  (0) 2022.03.08