📜  门| GATE-CS-2017(套装2)|第 61 题(1)

📅  最后修改于: 2023-12-03 15:12:44.355000             🧑  作者: Mango

题目介绍

本题属于 GATE-CS-2017 套装 2,是一道典型的算法题目。以下将详细介绍题目要求、解题思路和算法实现。

题目要求

给定一个无向图,每个顶点上有一个非负整数值。同时给定两个顶点 S 和 T。任务是找到一条从 S 到 T 的简单路径,使得路径上的经过的顶点值的乘积最小。输出该最小值。

解题思路
问题分析

根据题目要求,我们需要找到一条从 S 到 T 的简单路径,使得路径上的经过的顶点值的乘积最小。这里需要注意的是,重要的是路径上的乘积最小,而不是路径上的和最小,因此需要对问题进行转化。

贪心算法求解

根据乘积最小的要求,我们可以考虑采用贪心策略。具体来说,我们可以基于以下两个事实:

  1. 如果 a、b(a < b)是两个非负整数,那么 a+b < a * b,因此在路径上,我们应该尽可能地选择值较小的顶点。
  2. 如果当前路径乘积已经超过了当前最小值,那么无论以后如何选择顶点,得到的乘积一定不会更小,因此可以停止搜索。

利用这两个事实,我们可以得到基本的贪心算法框架:

  1. 初始化当前路径的乘积为 1,当前最小值为正无穷。
  2. 从 S 开始搜索路径,选择当前值最小的未被访问的相邻顶点,将其添加到路径中。
  3. 如果已经到达 T,将当前路径乘积与当前最小值比较,更新当前最小值。
  4. 如果当前路径乘积已经超过了当前最小值,停止搜索。
  5. 如果路径不包含 T,回溯到上一个顶点,将其标记为已访问,继续搜索。
算法实现
import math

def find_min_prod_path(graph, s, t):
    n = len(graph)
    visited = [False] * n
    curr_prod = 1   # 当前路径的乘积
    min_prod = math.inf  # 当前最小路径乘积

    def dfs(v):
        nonlocal curr_prod, min_prod
        
        if v == t:
            min_prod = min(min_prod, curr_prod)
        elif curr_prod < min_prod:
            visited[v] = True
            min_val = math.inf
            next_v = None
            
            for j in range(n):
                if graph[v][j] != 0 and not visited[j] and graph[v][j] < min_val:
                    min_val = graph[v][j]
                    next_v = j
            
            if next_v is not None:
                curr_prod *= min_val
                dfs(next_v)
                curr_prod //= min_val
            
            visited[v] = False
    
    dfs(s)
    return min_prod
总结

本题采用了基于贪心算法的搜索解法,时间复杂度为 O(n^2),空间复杂度为 O(n)。当然,还有其他算法可以解决该问题,例如 Dijkstra 算法等,但是均需要对题目进行转化,将原问题转化为求最短路径问题。因此,本题的贪心算法解法相对简单,易于理解和实现。