문제링크 : https://www.acmicpc.net/problem/4811
4811번: 알약
입력은 최대 1000개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄이며, 병에 들어있는 약의 개수 N ≤ 30 가 주어진다. 입력의 마지막 줄에는 0이 하나 주어진다.
www.acmicpc.net
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 987654321;
int N;
ll dp[31][31]; //w(한 조각), h(반 조각)
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
while(1)
{
cin >> N;
if(!N) break;
for(int i=0; i<=30; i++) dp[0][i]=1; //초기값 (첫날 약 한개)
for(int i=1; i<=30; i++) //w
{
for(int j=0; j<=30; j++) //h
{
if(!j) dp[i][0] = dp[i-1][1]; //직전 한조각 확정 -> [i-1][j+1]
else dp[i][j] = dp[i-1][j+1] + dp[i][j-1]; //한조각 -> [i-1][j+1], 반조각 -> [i][j-1]
}
}
cout << dp[N][0] << "\n";
}
return 0;
}
앞서 한 조각을 골랐는지, 반 조각을 골랐는지에 대해 염두를 두고 점화식을 세워야한다. (dp[w][h] : w 한 조각, h 반 조각)
기본적인 점화식은 dp[i-1][j+1] + dp[i][j-1]이다.
dp[i-1][j+1]의 경우는 한조각을 고른 경우다.
한 조각을 반으로 쪼개므로 w는 감소하고 반으로 쪼갬으로써 반조각이 생겼으므로 h가 증가한다.
dp[i][j-1]의 경우는 반 조각을 고른 경우다.
이 경우는 단순하게 h만 감소한다.
추가적으로 주의해야 할 것은 w가 0인 경우와 h가 0인 경우이다.
먼저 w가 0인 경우부터 보면 이는 초기화에 사용되기도 한다.
문제에 주어진 조건에 따라 처음 조각은 한조각으로 고정이고, 첫날 행동은 이 한 조각을 꺼내서 반은 먹고 반은 다시 집어 넣어서 dp[0][i]가 된 상태이다.
이 행동은 첫날 고정임에따라 경우의 수가 1가지로 초기값이 1로 정해진 것을 알 수 있다.
다음으로 h가 0인 경우를 보면 반조각이 없고 한 조각만 있는 상태이다.
현재 한 조각짜리만 있는 상태이므로 정해진 행동은이 한 조각를 먹고 남은 반을 다시 넣어두는 행위 뿐이다.
따라서 w가 감소하고 (한조각 갯수 감소) h가 증가한다. (반조각 갯수 증가)
이렇게 dp 식을 갱신하고 주어진 알약갯수인 N에 따른 dp[N][0]의 값을 출력시켜주면 된다.
'백준 > 골드' 카테고리의 다른 글
[백준 2624번] 동전 바꿔주기 (C++) (0) | 2023.11.28 |
---|---|
[백준 17069번] 파이프 옮기기 2 (C++) (0) | 2023.11.27 |
[백준 2240번] 자두나무 (C++) (0) | 2023.11.25 |
[백준 1516번] 게임 개발 (C++) (0) | 2023.11.24 |
[백준 12869번] 뮤탈리스크 (C++) (0) | 2023.11.23 |