[BOJ 4811] 알약
2024. 12. 5. 18:11ㆍBaekjoon
728x90
- 문제 요약
70세 박종수 할아버지는 매일 매일 약 반알을 먹는다. 손녀 선영이는 종수 할아버지에게 약이 N개 담긴 병을 선물로 주었다.
첫째 날에 종수는 병에서 약 하나를 꺼낸다. 그 다음, 그 약을 반으로 쪼개서 한 조각은 먹고, 다른 조각은 다시 병에 넣는다.
다음 날부터 종수는 병에서 약을 하나 꺼낸다. (약은 한 조각 전체 일 수도 있고, 쪼갠 반 조각 일 수도 있다) 반 조각이라면 그 약을 먹고, 아니라면 반을 쪼개서 한 조각을 먹고, 다른 조각은 다시 병에 넣는다.
종수는 손녀에게 한 조각을 꺼낸 날에는 W를, 반 조각을 꺼낸 날에는 H 보낸다. 손녀는 할아버지에게 받은 문자를 종이에 기록해 놓는다. 총 2N일이 지나면 길이가 2N인 문자열이 만들어지게 된다. 이때, 가능한 서로 다른 문자열의 개수는 총 몇 개일까?
(입력은 최대 1000개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄이며, 병에 들어있는 약의 개수 N ≤ 30 가 주어진다. 입력의 마지막 줄에는 0이 하나 주어진다.)
- 알고리즘 정리
dp[a][b] = 한 조각 알약의 개수가 a, 반 조각 알약의 개수가 b일 때, 가능한 서로 다른 문자열의 개수
위와 같이 DP 테이블 정의를 해두고, 재귀로 구현해 주면 됩니다.
- 코드 작성
#include<bits/stdc++.h>
using namespace std;
#define MAX 61
typedef long long ll;
int n;
ll dp[MAX][MAX];
ll f(int a,int b){
if(!a){
return 1;
}
ll &ret=dp[a][b];
if(ret!=-1){
return ret;
}
ret=0;
if(a>0){
ret+=f(a-1,b+1);
}
if(b>0){
ret+=f(a,b-1);
}
return ret;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
while(true){
cin>>n;
if(n==0){
break;
}
memset(dp,-1,sizeof(dp));
cout<<f(n-1,1)<<endl;
}
}
728x90
'Baekjoon' 카테고리의 다른 글
[BOJ 8980] 택배 (0) | 2024.12.06 |
---|---|
[BOJ 1947] 선물 전달 (0) | 2024.12.05 |
[BOJ 2229] 조 짜기 (0) | 2024.12.04 |
[BOJ 1016] 제곱 ㄴㄴ 수 (0) | 2024.11.22 |
[BOJ 19951] 태상이의 훈련소 생활 (1) | 2024.11.21 |