풀이
해설
자연수 N이 주어지고, N을 구성할 수 있는 제곱수들의 수를 구하는 문제이다.
모든 자연수는 최대 자연수 4개의 제곱수의 합
으로 표현할 수 있다고 라그랑주에 의해 증명이 되었다.
나의 경우 문제의 자연수를 제곱수가 2이상인 자연수로 착각해서 오래걸렸다.
풀이 과정은 다음과 같다.
- 배열에 1부터 N까지의 값을 저장한다.
(i-j^2)+1
값을 사용해 값을 구해나간다. i는 1부터 N까지 순회하는 자연수를 의미한다.
1번의 의미를 1*1
의 값의 개수라고 생각해보자. 그리고 배열을 돌면서 (i-j^2)+1
를 적용시킨다. 이것을 다음과 같은 코드로 적용시킬 수 있다.
for (int i = 1; i <= N; i++) {
for (int j = 1; j*j <= i; j++) {
dp[i] = Math.min(dp[i], dp[i - j*j] + 1);
}
}
- 구할 수 있는 자연수의 최소개수을 출력하는 조건이었기 때문에 최소개수을 구한다.
dp[i - j*j] + 1
을 구하면서 dp배열을 순회했다면, 해당 배열에는 자연수(i)에 대한 자연수의 최소 개수가 저장될 것이다.dp[i]
에는 i를 구할 수 있는 자연수의 개수가 들어있다.- 변경되지 않았다면 i에 해당하는 자연수가 들어있을 것이다.
dp[i - j*j]
는j*j
에 해당하는 자연수의 개수를 빼는 작업과 같다.- 즉,
j*j
에 해당하는 자연수를 제곱근으로 보고+1
로 치환하는 것으로 생각하면 된다.
시간복잡도
2중 for문을 사용하여 1부터 N까지의 최소 제곱 수의 개수를 구한다.
바깥쪽의 반복문은 N번 실행되고, 내부의 반복문은 i
의 제곱근까지 실행된다.
따라서 시간복잡도는 O(NrootN)이다.
코드
package ForSquares_17626;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
br.close();
int[] dp = new int[N + 1];
for (int i = 1; i <= N; i++) {
dp[i] = i;
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j*j <= i; j++) {
dp[i] = Math.min(dp[i], dp[i - j*j] + 1);
}
}
System.out.println(dp[N]);
}
}
Reference
'Problem Solving' 카테고리의 다른 글
[백준 11727] 2×n 타일링 2 (0) | 2023.03.22 |
---|---|
[프로그래머스] 기지국 설치 (0) | 2023.03.21 |
[백준 1504] 특정한 최단 경로 (0) | 2023.03.17 |
[백준 1676] 팩토리얼 0의 개수 (0) | 2023.03.17 |
[백준 1629] 곱셈 (0) | 2023.02.08 |