Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ 알고리즘 풀이: T초 후 개구리가 목표 정점에 있을 확률 구하기

문제 소개

n개의 정점으로 구성된 무방향 트리가 하나 주어진다고 가정해 봅시다. 정점에는 1부터 n까지 번호가 붙어 있습니다. 개구리는 정점 1에서 점프를 시작하며, 현재 정점과 인접한 아직 방문하지 않은 정점으로 1초에 한 번씩 점프할 수 있습니다. 단, 이미 방문한 정점으로는 되돌아갈 수 없습니다.

점프할 수 있는 정점이 여러 개라면 개구리는 동일한 확률로 그중 하나를 무작위로 선택해 이동하고, 더 이상 이동할 곳이 없다면 같은 정점 위에 영원히 머무르게 됩니다.

트리는 간선(edge) 배열의 형태로 주어지며, 우리가 구해야 하는 값은 t초 후 개구리가 target 정점 위에 있을 확률입니다.

예시

입력이 n = 7, t = 2, target = 4이고 트리가 아래와 같을 때 −

C++ 알고리즘 풀이: T초 후 개구리가 목표 정점에 있을 확률 구하기

출력은 0.1666이 됩니다. 그래프를 보면 개구리는 정점 1에서 시작하여 1초 후 0.3333의 확률로 정점 2로 점프한 뒤, 이어서 2초 후 0.5의 확률로 정점 4로 점프합니다. 따라서 2초 후 개구리가 정점 4에 있을 확률은 0.3333 × 0.5 ≈ 0.1667(0.166667)입니다.

풀이 접근 방법

이 문제는 다음 단계를 따라 해결할 수 있습니다 −

  • ret := 1로 초기화합니다.
  • 방문한 정점을 기록할 집합(set) visited를 정의합니다.
  • dfs() 함수를 정의합니다. 이 함수는 node, start, 간선 리스트 g, time, t, 스택 st를 매개변수로 받습니다.
  • node가 visited에 이미 존재하면 false를 반환합니다.
  • node를 visited에 추가합니다.
  • node가 1과 같다면 tt := time, ok := true로 설정한 뒤 true를 반환합니다.
  • i := 0부터 g[node]의 크기 미만까지 1씩 증가시키며 반복합니다 −
    • g[node][i]를 st에 push합니다.
    • dfs(g[node][i], start, g, time + 1, t, st)의 결과가 true이면 true를 반환합니다.
    • 그렇지 않으면 st에서 요소를 pop합니다.
  • false를 반환합니다.
  • 메인 메서드에서는 다음을 수행합니다 −
  • ret := 1, ok := false로 초기화합니다.
  • 크기가 n + 1인 리스트 배열 graph와 graph2를 정의합니다.
  • i := 0부터 edges의 크기 미만까지 반복하며 graph[edges[i][0]]에 edges[i][1]을, graph[edges[i][1]]에 edges[i][0]을 추가해 양방향 그래프를 구성합니다.
  • 스택 st를 정의합니다.
  • dfs(target, target, graph, 0, t, st)를 호출해 target에서 정점 1까지의 경로를 역으로 찾습니다.
  • 스택이 비어 있지 않은 동안 반복합니다 −
    • node := st의 최상위 요소
    • sz := graph[node]의 크기 (단, node가 1이 아니면 1 감소)
    • ret := ret × (1.0 / sz)
    • st에서 요소를 pop합니다.
  • tt > t이면 0을 반환합니다. (target에 도달하는 데 필요한 시간이 t를 초과하는 경우)
  • tt == t이면 ret을 반환합니다.
  • tt < t && target == 1 && graph[target].size() >= 1이면 0을 반환합니다.
  • 마지막으로, tt < t이면서 graph[target].size() > 1이면 0을, 그렇지 않으면 ret을 반환합니다. 개구리가 t초 이전에 도착했지만 계속 이동해야 하는 상황이라면 결국 target을 떠나게 되기 때문입니다.

다음 구현 예제를 통해 더 자세히 이해해 봅시다 −

예제 코드

#include <bits/stdc++.h>
using namespace std;
class Solution {
   public:
   double ret = 1;
   bool ok;
   set<int> visited;
   int tt;
   bool dfs(int node, int start, vector<int> g[], int time, int t,
   stack<int>& st){
      if (visited.count(node))
      return false;
      visited.insert(node);
      if (node == 1) {
         tt = time;
         ok = true;
         return true;
      }
      for (int i = 0; i < g[node].size(); i++) {
         st.push(g[node][i]);
         if (dfs(g[node][i], start, g, time + 1, t, st))
         return true;
         ;
         st.pop();
      }
      return false;
   }
   double frogPosition(int n, vector<vector<int> >& edges, int t,
   int target){
      ret = 1;
      ok = false;
      vector<int> graph[n + 1];
      vector<int> graph2[n + 1];
      for (int i = 0; i < edges.size(); i++) {
         graph[edges[i][0]].push_back(edges[i][1]);
         graph[edges[i][1]].push_back(edges[i][0]);
      }
      stack<int> st;
      dfs(target, target, graph, 0, t, st);
      while (!st.empty()) {
         int node = st.top();
         double sz = (double)graph[node].size();
         if (node != 1)
         sz--;
         ret *= (1.0 / sz);
         st.pop();
    }
      if (tt > t)
      return 0;
      if (tt == t)
      return ret;
      if (tt < t && target == 1 && graph[target].size() >= 1)
      return 0;
      return tt < t && graph[target].size() > 1 ? 0 : ret;
   }
};
main(){
   Solution ob;
   vector<vector<int>> v = {{1,2},{1,3},{1,7},{2,4},{2,6},{3,5}};
   cout << (ob.frogPosition(7,v,2,4));
}

입력

7, {{1,2},{1,3},{1,7},{2,4},{2,6},{3,5}}, 2, 4

출력

0.166667