일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Overfitting
- 자바스크립트
- 미래는_현재와_과거로
- pytorch
- dfs
- DP
- dropout
- 다익스트라
- 백트래킹
- 크루스칼
- c++
- NEXT
- 조합론
- BFS
- 가끔은_말로
- 2023
- 알고리즘
- 분할 정복
- tensorflow
- back propagation
- 가끔은 말로
- 회고록
- object detection
- 플로이드 와샬
- lazy propagation
- 우선 순위 큐
- 문자열
- 세그먼트 트리
- 너비 우선 탐색
- 이분 탐색
- Today
- Total
Doby's Lab
[알고리즘] 백준 17626번: Four Squares (C++), 오래간만에 DP 포스팅 본문
오래간만에 DP문제를 풀었다. 이번 문제는 점화식이 꽤 어렵지 않았다. 하지만, 틀린 점화식이었다.
작성했던 코드는 이랬다.
#include <iostream>
#include <cmath>
using namespace std;
int cache[50001] = { 0, };
int main() {
int n;
cin >> n;
cache[1] = 1;
cache[2] = 2;
cache[3] = 3;
int num = 2;
for (int i = 4; i <= n; i++) {
if (i % (num * num) == 0) {
cache[i] = 1;
num++;
}
else {
cache[i] = cache[i - 1] + 1;
}
}
cout << cache[n];
return 0;
}
두 가지 문제
이럴 경우 두 가지의 문제가 발생한다. 여러 가지 제곱수가 들어가지 못하는 점
예를 들어, 8이면 2^2 + 2^2 형태로 나타내는데 2^2 + 1^2 + 1^2 + 1^2 + 1^2 + 1^2의 형태로 밖에 나타내지 못한다.
그리고, 12의 경우 뺄 수 있는 값 중 가장 큰 값인 9(3^2)의 값이 빠져나가면 1^2이 3번 더해져 12의 값을 인풋으로 넣으면 4가 리턴된다. 하지만, 이는 그리디 알고리즘 같은 해결 방법에다가 이는 최적의 해가 아니다. 12의 경우 2^2를 3번 더하면 12가 완성된다. 즉, 12가 가질 수 있는 최적의 해는 3이다.
포인트
이 문제는 12 같은 경우를 면하기 위해 모든 경우의 수를 다 세어보고, 그중에 최솟값을 구해야 한다. 그런 의미에서 알고리즘 분류를 보면 브루트 포스 알고리즘이라고 되어있다.
그렇게 되어서 나올 수 있는 코드는 이랬다.
#include <iostream>
#include <cmath>
using namespace std;
int cache[50001] = { 0, };
int main() {
int n;
cin >> n;
cache[1] = 1;
for (int i = 1; i <= n; i++) {
cache[i] = cache[1] + cache[i - 1];
for (int j = 2; j * j <= i; j++) {
cache[i] = min(cache[i], 1 + cache[i - j * j]);
}
}
cout << cache[n];
return 0;
}
cache[i] = cache[1] + cache[i - 1]의 뜻은 기존의 값에서 1의 제곱을 더해서도 그 값을 구할 수 있기 때문에 하나의 경우의 수로 처리해주었다. 그다음부터 for문은 어떤 제곱수를 늘려가면서 예를 들어, 10이라면
cache[4] + cache[6]
cache[9] + cache[1]
의 형태로 나타내가며 1 + cache[i - j * j]의 코드에서 1을 더해주는 값이 제곱수를 나타내는 것을 알 수 있다.
min 함수를 통해 최솟값을 도출해낸다.
느낀 점
여전히 점화식의 접근이 어려웠다. 더군다나 이번 문제는 DP로 풀어야 하는데 나도 모르게 무의식적으로 그리디 알고리즘으로 풀려했었던 걸 보면 아직 이쪽 부분은 내가 논리력이 많이 부족하구나를 깨닫는다. 점화식, 즉 관계식에 대해 많은 공부를 해야 한다.
'PS > BOJ' 카테고리의 다른 글
[알고리즘] 백준 17266번: 어두운 굴다리 (C++), 아이디어 능력이 더 좋아지면 좋겠다 (0) | 2021.10.27 |
---|---|
[알고리즘] 백준 4307번: 개미 (C++) (0) | 2021.10.27 |
[알고리즘] 백준 1074번: Z (C++), 단순한 재귀가 아닌 분할 정복 (0) | 2021.10.23 |
[알고리즘] 백준 2630번: 색종이 만들기 (C++), 분할 정복 드디어 (0) | 2021.10.23 |
[자료구조] 백준 7662번: 이중 우선순위 큐 (C++), 두 큐를 하나처럼, 싱크의 핵심 (0) | 2021.10.21 |