[BOJ, Python] 1699번_제곱수의 합

2026. 7. 31. 14:53·Algorithm/Algorithm

이 글은 Velog에서 이전한 글입니다. Velog 원문 보기

백준 1699번

1차 코드(실패)

import sys
input = lambda: sys.stdin.readline().rstrip()
import math

N = int(input())
dp = [int(1e9)]*(N+1) # 1~N의 제곱수 항 최소 개수를 표현할 리스트
for i in range(1, int(math.sqrt(N))+1):
    dp[i**2] = 1

# 10을 만드는 최소항은 3^2(9) + 1^2
# 11을 만드는 경우 11보다 작은 수 중 가장 큰 제곱수를 빼고 그 수를 만드는 경우를 더해주면 된다.
for i in range(2, N+1):
    if dp[i] == 1:
        continue

    dp[i] = min(dp[i],
                1+dp[i-int(math.sqrt(i))**2])

print(dp[N])

현재 코드의 문제점
현재 코드는 N보다 작은 수 중 가장 큰 제곱수(M)을 N에서 빼고 그 뺀 수의 제곱수 최소항 갯수+1을 해서 제곱수 최소항의 갯수를 구하는 방식이다.
그러나 허점이 존재한다.

예를 들어, N이 14458인 경우 현재의 방식으로 하면 N-M=58이고, 58의 최소항의 갯수는 2이다. 그러므로 결과가 2+1=3이 나온다. 하지만 83^2+87^2=14458 이기에 N=14458의 최소항의 갯수는 2이다.
즉, 현재 코드는 정확한 최소항의 갯수를 찾지 못한다.

개선 방향
우선 N-M의 최소항의 갯수+1 공식부터 잘못됐다.
메모리를 신경쓰지 않는다면 가장 간단한 방법은 1~N의 제곱근(존재하는 경우) 범위에 존재하는 모든 제곱수를 N에서 빼고 그 수의 최소항의 갯수+1의 경우의 수를 모두 탐색하는 것이다.

2차 코드(성공)

import sys
input = lambda: sys.stdin.readline().rstrip()
import math

N = int(input())
dp = [int(1e9)]*(N+1) # 1~N의 제곱수 항 최소 개수를 표현할 리스트
for i in range(1, int(math.sqrt(N))+1):
    dp[i**2] = 1

for i in range(2, N+1):
    if dp[i] == 1:
        continue

    for j in range(int(math.sqrt(i)), 0, -1):
        dp[i] = min(dp[i],
                1+dp[i-j**2])

print(dp[N])

결과

코드는 성공했지만 많은 메모리 사용률과 높은 시간 복잡도를 해결하는 더 좋은 방법이 존재할 것 같다고 생각해서 다른 사람의 코드를 참고해서 다시 코드를 짜봤다.

최종 코드

import sys
input = lambda: sys.stdin.readline().rstrip()
import math

N = int(input())
dp = [int(1e9)]*(N+1) # 1~N의 제곱수 항 최소 개수를 표현할 리스트
for i in range(1, int(math.sqrt(N))+1):
    dp[i**2] = 1

for i in range(2, N+1):
    if dp[i] == 1:
        continue

    for j in range(int(math.sqrt(i)), 0, -1):
        if dp[i] > 1+dp[i-j**2]:
            dp[i] = 1+dp[i-j**2]

print(dp[N])

크게 변경된 부분은 없고, if dp[i] > 1+dp[i-j**2]: 기존 min으로 최소항의 갯수를 구하던 방식에서 if문으로 먼저 검증을 하는 방식으로 변경했다. 기존 방식은 모든 경우의 수에 대해서 min함수를 사용했는데 이처럼 if문으로 검증을 해준다면 min 함수를 사용하지 않고 dp 리스트가 변경되는 횟수를 감소시킬 수 있다.

결과

'Algorithm > Algorithm' 카테고리의 다른 글

[Leetcode, Python] 300. Longest Increasing Subsequence 풀이  (0) 2026.07.31
[BOJ, Python] 백준 NZEC(Non-Zero Exit Code) 오류  (0) 2026.07.31
✏️ [Algorithm] itertools 라이브러리에 대해서  (0) 2026.07.30
[BOJ, Python] 백준 3151번_합이 0  (0) 2026.07.30
[BOJ, python] 20922번_겹치는 건 싫어  (0) 2026.07.30
'Algorithm/Algorithm' 카테고리의 다른 글
  • [Leetcode, Python] 300. Longest Increasing Subsequence 풀이
  • [BOJ, Python] 백준 NZEC(Non-Zero Exit Code) 오류
  • ✏️ [Algorithm] itertools 라이브러리에 대해서
  • [BOJ, Python] 백준 3151번_합이 0
pp8817
pp8817
공부한 내용, 개발 관련 지식, 트러블 슈팅 등을 기록합니다. 이전 블로그: https://velog.io/@pp8817/posts
  • pp8817
    끄적이는 개발 log
    pp8817
  • 전체
    오늘
    어제
    • 분류 전체보기 (273)
      • Project (71)
        • 척척학사 (29)
        • Book (23)
        • Saynow (3)
        • YAPP 27기 (4)
        • 나의 작은 프로젝트 (10)
        • Landit (2)
      • Backend (88)
        • Spring (13)
        • Spring MVC (13)
        • Spring Security (4)
        • JPA (26)
        • Database (19)
        • HTTP·Web (13)
        • Architecture (0)
      • Language·CS (59)
        • Java·Kotlin (5)
        • CS Interview (17)
        • Backend Interview (5)
        • Concepts (32)
      • Algorithm (25)
        • Algorithm (24)
        • 소마 알고리즘 스터디 (1)
      • Infra (8)
      • Troubleshooting (11)
      • Retrospective (6)
      • Etc (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    BOJ
    Algorithm
    나의 작은 프로젝트
    java
    트러블슈팅
    척척학사
    interview
    CS Interview
    Spring
    OS
    Project
    Spring MVC
    Book
    Python
    object
    게시판
    http
    jpa
    HTTP WEB 기본 지식
    개념 정리!
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
pp8817
[BOJ, Python] 1699번_제곱수의 합
상단으로

티스토리툴바