首先是30分的做法:
对一个树,找遍历其中几个点的最短路:
回到起点的做法:dfs遍历一遍,就是把每个边走了两倍。
不回到起点的做法:会停在某个点上。ans = 总长度 - 根到最后一个点的长度
(停在距离根节点最远的点上,ans最小)
这是一种贪心的思想,预处理出所有的起点进行遍历得到的最短路。
接着就是从k个食材中选m个
这个是非常经典的重复覆盖问题。
n行中选m行,使得每一列都有一个1.也就是找到每列都有一个1的话,最少有多少行?
Dancing Links
or 用状态压缩DP来做。愤怒的小鸟。
代码分析:
need[i][j] 表示 第i个酒店是否需要第j个食材
state表示选哪些起点
d[][]表示第i个酒店选第j个食材一共要走多少路
用邻接表存酒店直接的路和长度
迭代每个起点,每个食材,用一个dfs遍历求出从起点到遍历完所有需要食材的酒店后的边的长度的两倍,以及当前离起点最远的点的距离
再用一个二分法,列举所有状态压缩后的int,计算在这个状态中最少需要多少行能覆盖所有食材,如果行数大于m,就增大状态,直到找到一个最小的状态,它的