1699번: 제곱수의 합
어떤 자연수 N은 그보다 작거나 같은 제곱수들의 합으로 나타낼 수 있다. 예를 들어 11=32+12+12(3개 항)이다. 이런 표현방법은 여러 가지가 될 수 있는데, 11의 경우 11=22+22+12+12+12(5개 항)도 가능하다
www.acmicpc.net
간단한 dp 문제였다.
자연수 N을 제곱수의 합으로 나타낼 때 최소항의 개수를 찾는 방법은 min(1 + [N - (제곱한 값이 N보다 작거나 같은 수들의 제곱수)]의 항의 개수) 이다.
예를 들어 N = 10 일 때 최소 항의 개수는 dp[10] = min( 1 + dp[10-1], 1 + dp[10-4], 1 + dp[10-9] ) 로 나타낼 수 있다.
따라서 점화식은 다음과 같다.
for(i = 1; i<=N; i++)
if(i*i <= N) dp[N] = min(dp[N], 1 + dp[N-i*i])
#include <iostream>
using namespace std;
const int INF = 987654321;
int memo[100001];
int min(int a, int b) { return a < b ? a : b; }
int Topdown(int N)
{
if (N == 0) return 0;
int& ret = memo[N];
if (ret != 0) return ret;
ret = INF;
for (int i = 1; i <= N; i++)
{
if (i*i > N) break;
ret = min(ret, 1 + Topdown(N - i * i));
}
return ret;
}
int Bottomup(int N)
{
memo[0] = 0;
memo[1] = 1;
for (int i = 2; i <= N; i++)
{
memo[i] = INF;
for (int j = 1; j <= N; j++)
{
if (j*j > i) break;
memo[i] = min(memo[i], 1 + memo[i - j * j]);
}
}
return memo[N];
}
int main(void)
{
int N;
cin >> N;
cout << "top-down: " << Topdown(N) << endl;
cout << "bottom-up: " << Bottomup(N) << endl;
return 0;
}
알고리즘 200일 프로젝트 - 78 day
'알고리즘 > BOJ' 카테고리의 다른 글
백준 9251번: LCS (0) | 2020.06.23 |
---|---|
백준 11055번: 가장 큰 증가 부분 수열 (0) | 2020.06.22 |
백준 2293번: 동전 1 (0) | 2020.06.20 |
백준 11057번: 오르막 수 (0) | 2020.06.18 |
백준 1010번: 다리 놓기 (0) | 2020.06.18 |