LeetCode2646. 最小化旅行的价格总和

深度优先搜索+动态规划

题目链接:最小化旅行的价格总和

深度优先搜索

为了使旅行的价格总和最小,那么每次旅行的路径必定是最短路径。

每次旅行trips[i]都是独立的,所以可以采用count[]来记录,所有旅行中每个节点的访问次数

最短路径可以采用深度优先搜索

TIP:获取所有的节点的访问次数后,总价格为:

priceTotal = Σ price[node] * count[node]

树形DP

以节点0为树的根节点

状态表示:

  • f[node][0]:以node为根节点的子树,node节点价格不变时,整个子树的最小价格
  • f[node][1]:以node为根节点的子树,node节点价格减半时,整个子树的最小价格

状态计算:

  • f[node][0] = Σ min(f[child][0], f[child][1]):当前节点价格不变,孩子可以 减半/不变
  • f[node][1] = Σ f[child][0]:当前价格减半,孩子只能 不变

答案

min(f[0][0], f[0][1]):以节点0为树的根节点,priceTotal = Σ price[node] * count[node]的最小值

func minimumTotalPrice(n int, edges [][]int, price []int, trips [][]int) int {
	var (
		g     [][]int // 邻接表
		count []int   // 最短路径中,每个节点的访问次数
		f     [][]int // 动态规划
	)
	g = make([][]int, n)
	count = make([]int, n)
	f = make([][]int, n)
	for i := 0; i < n; i++ {
		g[i] = make([]int, 0)
		f[i] = make([]int, 2)
	}
	for _, e := range edges {
		g[e[0]] = append(g[e[0]], e[1])
		g[e[1]] = append(g[e[1]], e[0])
	}

	var dfs func(cur, fa, end int) bool
	dfs = func(cur, fa, end int) bool {
		// 返回当前节点能否递归到终点
		if cur == end {
			count[cur]++
			return true
		}
		for _, child := range g[cur] {
			if child == fa {
				continue
			}
			if dfs(child, cur, end) {
				count[cur]++
				return true
			}
		}
		return false
	}
	for _, t := range trips {
		dfs(t[0], -1, t[1])
	}

	var dp func(cur, fa int)
	dp = func(cur, fa int) {
		f[cur][0] = price[cur] * count[cur]
		f[cur][1] = price[cur] / 2 * count[cur]
		for _, child := range g[cur] {
			if child == fa {
				continue
			}
			dp(child, cur)
			f[cur][0] += min(f[child][0], f[child][1])
			f[cur][1] += f[child][0]
		}
	}
	dp(0, -1)
	return min(f[0][0], f[0][1])
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值