티스토리 뷰

 

문제 링크 : https://www.acmicpc.net/problem/17626

 

17626번: Four Squares

라그랑주는 1770년에 모든 자연수는 넷 혹은 그 이하의 제곱수의 합으로 표현할 수 있다고 증명하였다. 어떤 자연수는 복수의 방법으로 표현된다. 예를 들면, 26은 52과 12의 합이다; 또한 42 + 32 + 1

www.acmicpc.net

 

탑다운, 바텀업 모두를 빠르게 작성하는 연습.

 

자연수 i 를 제곱수들의 합으로 표현할 때 필요한 제곱수의 개수를 최소화하라는 문제이니, 이를 dp[i] 라 두자.

i 이하의 수에 대해서 최소화된 개수를 모두 알고 있다면 다음이 성립한다.

$$ dp[i]= \min\limits_{j^2 \le i}  dp[i-j^2] +1$$

 

1. Bottom-UP

두 가지 바텀업 구현을 살펴본다.

dp[0]=0, 그 외의 값들은 매우 큰 값으로 초기화하는 것은 당연.

 

주어진 i 에서 더 큰 값들을 채워나가는 방식의 바텀업 구현부터.

 

#include<bits/stdc++.h>

using namespace std;

int dp[50001];

int main(){
    int n; scanf("%d",&n);
    for(int i=1;i<=n;i++) dp[i]=INT_MAX;
    
    for(int i=0;i<=n;i++){
        for(int j=1;i+j*j<=n;j++){
            dp[i+j*j]=min(dp[i+j*j], dp[i]+1);
        }
    }
    printf("%d\n", dp[n]);
}

 

주어진 i 를 앞에서 얻은 것들의 결과로 구현하는 방식은 다음과 같다.

 

#include<bits/stdc++.h>

using namespace std;

int dp[50001];

int main(){
    int n; scanf("%d",&n);
    
    for(int i=1;i<=n;i++){
        dp[i]=1e9;
        for(int j=1;j*j<=i;j++){
            dp[i]=min(dp[i], dp[i-j*j]+1);
        }
    }
    printf("%d\n", dp[n]);
}

 

2. Top-Down

base case 만 처리를 잘하면 된다.

 

#include<bits/stdc++.h>

using namespace std;

int dp[50001];

int recur(int n){
    if(n==0) return 0;
    
    int &ret=dp[n];
    if(ret) return ret;
    
    ret=INT_MAX;
    for(int i=1;i*i<=n;i++)
        ret=min(ret, recur(n-i*i)+1);
    
    return ret;
}

int main(){
    int n; scanf("%d",&n);
    printf("%d\n", recur(n));
}

 

 

 

반응형

'DS\Algo > Dynamic Programming' 카테고리의 다른 글

BOJ 2240 자두나무  (0) 2022.10.19
BOJ 15990 1, 2, 3 더하기 5  (0) 2022.09.27
BOJ 7579 앱  (1) 2022.09.25
BOJ 2011 암호코드(Alphacode)  (1) 2022.09.24
BOJ 12852 1로 만들기 2  (0) 2022.09.22
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
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
글 보관함