17626번: Four Squares
문제 라그랑주는 1770년에 모든 자연수는 넷 혹은 그 이하의 제곱수의 합으로 표현할 수 있다고 증명하였다. 어떤 자연수는 복수의 방법으로 표현된다. 예를 들면, 26은 52과 12의 합이다; 또한 42 +
www.acmicpc.net
#include <iostream>
using namespace std;
// 입력 받은 자연수까지의 모든 최솟값들을 구해놓을 배열
int ans[50001] = {0, 1, 2, 3, 1, 2};
// 제곱근들에 대한 배열
int sqr[225] = {0};
// i 번쨰에 대한 최솟값을 구하는 함수
int cntMin(int idx)
{
int min = 4;
for(int i = 1 ; i * i <= idx ; i++)
{
// 각 제곱값들 별로 완전 탐색, 제곱값을 뺀 값에 대한 최솟값은 이미 dp 배열에 존재
int n = ans[idx - sqr[i]];
if(n < min) min = n;
}
// 최솟값(min) + 특정 제곱값(1)
return min + 1;
}
int main(void)
{
int n;
cin >> n;
// 각 제곱값들은 갯수를 1로 초기화시켜줌
for(int i = 1 ; i < 225 ; i++)
{
sqr[i] = i * i;
ans[i * i] = 1;
}
// 1~n 까지 최솟값들을 배열에 저장
for(int i = 6 ; i <= n ; i++)
{
// 제곱값들은 하지 않음
if(ans[i] == 0)
{
ans[i] = cntMin(i);
}
}
cout << ans[n] << '\n';
}
[Approach]
1. 그리디한 느낌으로 가장 큰 제곱근부터 찾아서 구해나가거나 / 50000 이면 완전탐색으로 전부 다 찾아보는 방법이 있을 것 같다.
생각해보니 둘 다 동시에 적용해야 할 듯. 재귀로 빠지면 함수 스택이 너무 깊어질 것 같다.
도저히 안되겠는데, 정말 dp 배열 5만개를 다 만드는게 맞는걸까?
결국 DP 배열을 써서 맞긴 했는데, 뭔가 찝찝하다.
[Point]
1. 50000개 채우는게 생각보다 시간이 그렇게 오래걸리는 일은 아닌 것 같다.
2. 결국 이 문제도 완전 탐색 하는게 껄끄러워서 다른 방법을 계속 생각하다 오래 걸렸는데, 이 마인드를 어떻게 고쳐야 할지 모르겠다.
'PS > BOJ' 카테고리의 다른 글
[백준] 1676.cpp : 팩토리얼 0의 개수 (0) | 2020.06.29 |
---|---|
[백준] 17219.cpp : 비밀번호 찾기 (0) | 2020.06.29 |
[백준] 1075.cpp : 나누기 (0) | 2020.06.17 |
[백준] 5585.cpp : 거스름돈 (0) | 2020.06.16 |
[백준] 2309.cpp : 일곱 난쟁이 (0) | 2020.06.15 |