NUMB3RS (중하, p. 269)

어떻게 풀었나?#

이 이전 문제가 POLY인데, 책에는 NUMB3RS와 POLY모두 난이도 ‘중’으로 표시되어있다.

POLY 난이도가 거의 ‘상’에 가깝다면, NUMB3RS 난이도는 ‘하’에 가까운 것 같다.

난이도 ‘하’는 생각 자체가 필요 없는 문제들을 분류하였으므로, 이 문제는 ‘중하’로 결정했다.

정점 n에서 d일후 두니발 박사가 있을 확률을 f(n,d)로 나타내면,

$f(n,d) = \sum_{i=0}^{v[n].size()} (f(v[n][i],d-1)/v[v[n][i]].size())$

가 된다. (여기서 v[n]은 n의 인접 정점들만 저장한 vector를 의미한다.)


문제#

image.png


정답 코드#

#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> v;
int CHKVAL;
int chk[51][101];
double dp[51][101];
int p;
double f(int x, int d) {
    if(d==0) {
        if(x==p) return 1;
        else return 0;
    }
    if(chk[x][d] == CHKVAL) return dp[x][d];
    chk[x][d] = CHKVAL;
    double & ret = dp[x][d];
    ret=0;
    for(int i=0; i<v[x].size(); i++) {
        int y = v[x][i];
        ret += f(y,d-1)/v[y].size();
    }
    return ret;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int tc; cin >> tc;
    while(tc--) {
        int n,d,x; cin >> n >> d >> p;

        v.clear(); v.resize(n, vector<int>());

        CHKVAL++;
        for(int i=0; i<n; i++) {
            for(int j=0; j<n; j++) {
                cin >> x;
                if(x) {
                    v[i].push_back(j);
                    v[j].push_back(i);
                }
            }
        }
        int t; cin >> t;
        for(int i=0; i<t; i++) {
            cin >> x;
            printf("%.8lf ", f(x,d));
        }
        puts("");
    }
    return 0;
}