DAMPER's blog

[ALGOSPOT] 두니발 박사의 탈옥 (NUMB3RS) 본문

Problem Solving/알고리즘 문제해결전략

[ALGOSPOT] 두니발 박사의 탈옥 (NUMB3RS)

DAMPER 2021. 1. 22. 16:49
728x90

출처 : algospot.com/judge/problem/read/NUMB3RS

 

algospot.com :: NUMB3RS

두니발 박사의 탈옥 문제 정보 문제 위험한 살인마 두니발 박사가 감옥에서 탈출했습니다. 수배지를 붙이고 군경이 24시간 그를 추적하고 있지만 용의주도한 두니발 박사는 쉽사리 잡히지 않았

algospot.com

 

<문제>

위험한 살인마 두니발 박사가 감옥에서 탈출했습니다. 수배지를 붙이고 군경이 24시간 그를 추적하고 있지만 용의주도한 두니발 박사는 쉽사리 잡히지 않았습니다. d일이 지난 후에야 경찰은 프로그래밍의 천재인 찰리 교수)를 찾아왔습니다. 찰리 교수는 두니발 박사가 감옥에 남겨둔 노트를 분석해 다음과 같은 가설을 세웠습니다.

  • 두니발 박사는 검문을 피해 산길로만 이동한다.
  • 두니발 박사는 교도소를 탈출한 당일, 교도소와 인접한 마을 하나로 도망쳐 은신한다.
  • 두니발 박사는 수색을 피하기 위해 그 후 매일 인접한 마을로 움직여 은신한다.

이 가설을 검증하기 위해 교도소로부터 산길로 연결된 n 개 마을들의 지도를 위 그림과 같이 구했습니다. 두니발 박사가 이 가설에 맞춰 행동하고, 움직일 수 있는 마을이 여러 개 있을 경우 그 중의 하나를 임의로 선택한다고 합시다. d 일 후에 두니발 교수가 각 마을에 있을 확률을 계산하는 프로그램을 작성하세요.

예를 들어 위 지도에서 3번 마을에 교도소가 있다고 합시다. 탈옥 직후 두니발 교수는 0번, 1번, 2번, 4번, 5번 중의 한 도시를 임의로 골라 도망칩니다. 따라서 1일 후에 두니발 교수가 0번 마을에 숨어 있을 확률은 1/5이고, 2일 후에 1번 마을에 숨어 있을 확률은 1/15입니다.

 

<입력>

입력의 첫 줄에는 테스트 케이스의 수 c (1 <= c <= 50) 가 주어집니다. 그 후 각 줄에 지도에 포함된 마을의 수 n (2 <= n <= 50) 과 탈출 후 지금까지 지난 일수 d (1 <= d <= 100), 그리고 교도소가 있는 마을의 번호 p (0 <= p < n) 가 주어집니다. 마을은 0번부터 n-1 번까지 순서대로 번호가 매겨져 있습니다. 그 후 n 줄에는 각각 n 개의 정수로 행렬 A 가 주어집니다. i 번 행의 j 번 숫자 A[i][j] 가 1인 경우 i 번 마을에서 j 번 마을을 잇는 산길이 있다는 것을 의미하며, 0인 경우 길이 없다는 것을 의미합니다. 그 다음 줄에 확률을 계산할 마을의 수 t (1 <= t <= n) 가 주어지고, 그 다음 줄에 t 개의 정수로 확률을 계산할 마을의 번호 q (0 <= q < n) 가 주어집니다.

한 마을에서 다른 마을로 길이 있으면 반대 방향으로도 항상 있으며, 한 마을에서 자기 자신으로 연결되는 길은 없다고 가정해도 좋습니다.

 

<출력>

각 테스트 케이스마다 t 개의 실수로 각 마을에 두니발 박사가 숨어 있을 확률을 출력합니다. 10-7 이하의 절대/상대 오차가 있는 경우 정답으로 처리됩니다.

 

 

문제에 그래프를 그려줘서인지 뭔가 쉽게 접근할 수 있었습니다.(?)

BFS + DP 같은 느낌으로 접근했는데 나 풀고 나니까 마을 최대 갯수가 50개밖에 안되어서 그냥 모두 확인해도 되는 문제 였다.

 

문제 해결 방법은 간단하다.

i 일차 x마을에 두니발 박사가 있을 확률이 0%보다 크다면(k%라 하자.), i+1일차에 x마을로부터 갈 수 있는 모든 마을(cnt 갯수의 마을)에 (k/cnt)% 만큼 더해준다. 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>
#define swap(a,b) (a)^=(b)^=(a)^=(b)
#define endl '\n'
using namespace std;
typedef long long lld;
 
int main()
{
    ios_base::sync_with_stdio(NULL);
    cin.tie(NULL);
    cout.tie(NULL);
    int tc;
    cin>>tc;
    while(tc--)
    {
        int n, d, p;
        cin>>n>>d>>p;
        vector<vector<int>> v(n, vector<int>());
        vector<vector<double>> dp(d+1vector<double>(n, 0.0));
        vector<bool> check(n, false);
        queue<int> q;
        dp[0][p] = 1.0;
        q.push(p);
        
        int tmp;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                cin>>tmp;
                if(tmp) v[i].push_back(j);
            }
        }
 
        for(int i=1;i<=d;i++)
        {
            fill(check.begin(), check.end(), false);
            size_t size = q.size();
            while(size--)
            {
                int pret = q.front();
                q.pop();
                for(size_t j=0;j<v[pret].size();j++)
                {
                    int next = v[pret][j];
                    dp[i][next] += dp[i-1][pret]/v[pret].size();
                    if(!check[next])
                    {
                        check[next] = true;
                        q.push(next);
                    }
 
                }
            }
        }
        int check_num;
        cin>>check_num;
 
        cout<<fixed;
        cout.precision(12);
        for(int i=0;i<check_num;i++)
        {
            cin>>tmp;
            cout<<dp[d][tmp]<<" ";
        }
        cout<<endl;
 
    }
    return 0;
}
cs
728x90