Algorithm/dp

[맞음] 백준 4811 알약 c++ // 재귀dp, 경우의수는 +

Mini_96 2024. 4. 30. 21:59

https://www.acmicpc.net/problem/4811

 

1.의사코드

1. 알약을 1개꺼낸 경우 vs 반개꺼낸경우 계속 2분탐색이다.

2. 완탐? -> 2^30 -> 불가 -> dp?

3. 상태 : 큰알약갯수, 작은알약갯수 : 그때의 경우의수

4. 경우의수는 기저사례 -> return 1, 후 +하면 된다.

아래 그림과 같이 1이 리턴되고 거꾸로 타고오면서 그런 경우의 수가 모두 더해진다.

 

2. 전체코드

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

ll dp[34][34];

//큰알약남은갯수, 반알약남은갯수 : 그상태일때, 경우의수
ll dfs(int a, int b) {
    if (a==0 && b==0) return 1;
    if (dp[a][b] != -1) return dp[a][b];

    dp[a][b] = 0;
    if (a > 0)
        dp[a][b] += dfs(a - 1, b + 1);
    if (b > 0)
        dp[a][b] += dfs(a, b - 1);
    return dp[a][b];
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    while (1) {
        int tc;
        cin >> tc;
        if (tc == 0) break;

        memset(dp, -1, sizeof(dp));
        cout << dfs(tc,0)<<"\n";
    }


    return 0;
}

 

* 2회독 (25.3.15.) 맞음

  • return 1
  • and
  • ret += dfs()
  • 그림을 그리면서 return과 ret조건이 뭔지 찾는다.

 

  • 종료조건
    • 오답 : a<0 or b<0 
    • 개선 : 약을 전부먹어야 종료조건 (a==0 and b==0)