문제링크 : https://www.acmicpc.net/problem/1229
1229번: 육각수
육각수는 육각형을 이용해 정의할 수 있다. hn은 한 변에 점 1, 2, ..., n개가 있는 육각형을 점 하나만 겹치게 그렸을 때 존재하는 서로 다른 점의 개수이다. 그림 1 그림1은 h1, h2, h3, h4를 의미하며,
www.acmicpc.net
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 987654321;
vector<int>v;
int dp[10000001];
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int N;
cin >> N;
int num = 1, gap = 5;
while(num<=N) //가능한 육각수 미리 구해놓기
{
v.push_back(num);
num+=gap;
gap+=4; //공차 4
}
fill(&dp[0], &dp[10000001], MAX);
dp[0]=0; dp[1]=1;
for(auto i : v)
{
for(int j=i; j<=N; j++)
{
dp[j] = min(dp[j-i]+1, dp[j]); //최소값 갱신
}
}
cout << dp[N];
return 0;
}
먼저 가능한 육각수에 대해서 구해줬다.
다음과 같이 가능한 육각수들을 보면 규칙을 찾을 수 있다.
ex : 1 6 15 28 45 66
gap : 5, 9, 13, 17, 21 -> 공차가 4인 등차수열
위 규칙을 토대로 초기값인 1부터 gap을 더해주며 N이하로 가능한 최대의 육각수들을 구해서 벡터에 담아줬다.
위 벡터에서 담았던 값을 토대로 해당 값부터 N까지의 값을 탐색한다.
이때 dp[j-i]+1 과 dp[j]의 값을 비교하여 작은 값을 저장해준다.
처음 육각수인 1을 기준으로 하면 가능한 육각수가 1밖에 없기에 1 ~ 26의 값은 1 ~ 26일 것이다.
그다음 육각수인 6을 기준으로 시작하면 6은 이제 가능한 육각수가 생겼기에 1로 시작하여 11까지는 1 ~ 5일 것이다.
이제 12를 보면 dp[12-6]+1이기에 이는 dp[6]+1로 2인 것을 알 수 있다. 그전값인 dp[6]이 1이기에 해당 값은 2가 된다.
이런식으로 현재 값(12)에 현재 육각수의 값(6)을 빼줌으로써 그전값(6)의 확인을 통해 현재 값이 육각수의 합(6+6)으로 이루어지는지 확인을 할 수 있다.
이를 모든 N이하의 가능한 모든 육각수의 경우마다 N까지 탐색을 해서 반복하며, 이때 가장작은 값을 저장해준다.
'백준 > 골드' 카테고리의 다른 글
[백준 14002번] 가장 긴 증가하는 부분 수열 4 (C++) (0) | 2023.09.07 |
---|---|
[백준 1351번] 무한 수열 (C++) (0) | 2023.09.04 |
[백준 1759번] 암호 만들기 (C++) (0) | 2023.08.30 |
[백준 10942번] 팰린드롬? (C++) (0) | 2023.08.27 |
[백준 2467번] 용액 (C++) (0) | 2023.08.26 |