ALGOSPOT - SNAIL
알고리즘/동적 계획법문제
https://algospot.com/judge/problem/read/SNAIL
풀이
완전 탐색 코드를 먼저 만들었다. 비가 올 확률이 75%이고 비가 올때는 2m, 비가 오지 않을 확률이 25%이고 비가 오지 않을때는 1m씩 올라가므로 그냥 재귀적으로 함수를 호출해주며 m일이 지났을때 우물을 다 올라갔는지 확인해주는 코드를 작성했다.
#include <cstdio> int n,m; double solve(int cur, int day){ if(day == m) return cur >= n; return (0.25*solve(cur+1,day+1)) + (0.75*solve(cur+2,day+1)); } int main() { int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); printf("%.10lf\n",solve(0,0)); } }
잘 작동하지만 완전 탐색인만큼 큰 입력이 들어오면 엄청 오래 걸린다. 그러므로 메모이제이션을 적용해서 중복 계산을 하지 않도록 코드를 바꿔줘야 한다. dp[height][day] = day일째에 height만큼 올라 왔을때 우물 끝까지 올라갈 확률이라 하고 메모이제이션을 적용했다.
또한 아래와 같은 부분에 대해 고민을 하며 코드를 작성했다.
- double은 -1로 memset이 안되는거 같다. > 그래서 직접 for문으로 값을 초기화시켰다.
- 올라갈 수 있는 최대 높이는 N이 아니다. > N-1에서 비가 와 N+1까지 올라갈 수 있는 경우가 있으므로 배열 크기를 1 더 잡아줘야 한다.
#include <cstdio> int n,m; double dp[1003][1001]; double solve(int cur, int day){ if(day == m) return cur >= n; if(cur >= n) return 1.; double& ret = dp[cur][day]; if(ret != -1.) return ret; return ret = (0.25*solve(cur+1,day+1)) + (0.75*solve(cur+2,day+1)); } int main() { int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<=1002;i++) for(int j=0;j<=1000;j++) dp[i][j] = -1.0; printf("%.10lf\n",solve(0,0)); } }