前言
周赛依然没打~
本周主题:图路径枚举、深度优先搜索、贪心、矩阵枚举
题目:
- 240702每日一题—Maximum Path Quality of a Graph
- 240704每日一题—Minimum Moves to Pick K Ones
- 240707每日一题—Check if Move is Legal
图路径枚举(DFS)
Maximum Path Quality of a Graph
There is an undirected graph with n nodes numbered from 0 to n - 1 (inclusive). You are given a 0-indexed integer array values where values[i] is the value of the ith node. You are also given a 0-indexed 2D integer array edges, where each edges[j] = [uj, vj, timej] indicates that there is an undirected edge between the nodes uj and vj, and it takes timej seconds to travel between the two nodes. Finally, you are given an integer maxTime.
A valid path in the graph is any path that starts at node 0, ends at node 0, and takes at most maxTime seconds to complete. You may visit the same node multiple times. The quality of a valid path is the sum of the values of the unique nodes visited in the path (each node’s value is added at most once to the sum).
Return the maximum quality of a valid path.
Note: There are at most four edges connected to each node.
这题直接作为学习枚举图路径的素材了,对于数据范围小的图路径题可以考虑,由于原题通过时间范围限制了路径最大长度为10
且每个节点的度数不超过4
,则枚举的范围较小。
可以使用递归 + 回溯的方法进行枚举。递归函数记录当前所在的节点编号,已经过的路径的总时间以及节点的价值之和。如果当前在节点 u,我们可以枚举与 u 直接相连的节点 v 进行递归搜索。在搜索的过程中,如果我们回到了节点 0,就可以对答案进行更新;如果总时间超过了 maxTime,我们需要停止搜索,进行回溯。
1 | class Solution { |
矩阵枚举
Check if Move is Legal
You are given a 0-indexed 8 x 8 grid board, where board[r][c] represents the cell (r, c) on a game board. On the board, free cells are represented by ‘.’, white cells are represented by ‘W’, and black cells are represented by ‘B’.
Each move in this game consists of choosing a free cell and changing it to the color you are playing as (either white or black). However, a move is only legal if, after changing it, the cell becomes the endpoint of a good line (horizontal, vertical, or diagonal).
A good line is a line of three or more cells (including the endpoints) where the endpoints of the line are one color, and the remaining cells in the middle are the opposite color (no cells in the line are free).
Given two integers rMove and cMove and a character color representing the color you are playing as (white or black), return true if changing cell (rMove, cMove) to color color is a legal move, or false if it is not legal.
由题意可知,当前操作合法当且仅当从该点开始的 8 个方向(上下左右与对角线)中,至少有一个方向存在一个以该点为起点的好线段。
那么,我们可以枚举这 8 个方向,并对于每个方向验证是否存在以该点为起点的好线段。如果该点与对应方向下一个相同颜色的格点之间的所有格点(至少一个)均为另一种颜色,那么它们构成一个好线段。
我们用数对 (dx,dy) 来表示每个方向下一个格点相对于当前格点的行列下标变化量,并用函数 check(dx,dy) 来判断该方向是否存在以操作位置为起点的好线段。如果我们寻找到了符合要求的好线段,则返回 true;反之亦然。
1 | class Solution { |
贪心
题目:Minimum Moves to Pick K Ones
这题首先要先读明白题…首先有一个“01串”,目标是用最少的moves
捡起k
个$1$,起始状态是从串中的某个$1$开始的,我们叫这个$1$的下标为aliceIndex
,我们取走这个$1$使该位置变成$0$,此时还差k-1
个$1$需要捡。怎么捡其他的$1$呢?我们通过如下两种操作:
- 随便选一个$0$变成$1$,俗称点石成金,有最大操作数限制
maxChanges
; - 选两个邻接的$1$和$0$,下标分别为$x$和$y$,交换值,如果$y==aliceIndex$则捡起这个$1$。
因此,对于aliceIndex
左右两侧有$1$的情况,我们只需要$1$个动作就可以捡起,当两侧都为$0$时,通过点石成金和交换的组合动作来捡$1$,这里的分情况思想比较重要,我第一次做时就错在了从动作角度考虑,实际上分情况时应该注意“普适性”与“靠近终态”(这是我瞎总结的),因此应该从所有的$1$所处的位置考虑。情况如下:
- 情况一:先将 aliceIndex 邻近的数字设置为 1 ,然后交换数字,只需要两次行动就可以拾起一个 1 。
- 情况二:令 $n u m s[x]=1$ ,那么需要 $\mid x$-aliceIndex $\mid$ 次行动才可以拾起一个 1 ,根据 $x$ 的取值,又可以区分成两种类型:
- $x \in[$ aliceIndex -1 , aliceIndex +1$]$ ,那么最多需要 1 次行动就可以拾起一个 1 。
- $x \notin[$ aliceIndex -1 , aliceIndex +1$]$ ,那么最少需要 2 次行动才可以拾起一个 1 。
令 $f($ aliceIndex $)$ 表示数组 nums 在区间 $[$ aliceIndex -1 , aliceIndex +1$]$ 内的元素之和。
如果 $f($ aliceIndex $)+maxChanges \geq k$ ,那么最少行动次数肯定是先将区间 [aliceIndex -1 , aliceIndex + 1] 内的所有 1 拾起, 然后剩余的 1 根据情况一来拾起。
如果 $f($ aliceIndex $)+maxChanges <k$ ,那么可以贪心地先拾起情况一的所有 1 ,剩余 $k-maxChanges$个 1 根据情况二拾起。我们使用 $indexSum [i]$ 记录数组 $n u m s$ 在区间 $[0, i)$ 内所有值为 1 的元素下标之和,使用 $sum[i]$ 记录数组 nums 在区间 $[0, i)$ 所有元素之和。要使情况二的行动次数之和最少,那么拾起的 1 距离 aliceIndex 需要尽量近。我们使用二分算法来搜索最短距离 $d$ ,使得区间 $[aliceIndex-d, aliceIndex+d]$ 内的 1 数目大于等于 $k-maxChanges$ 。记选择的区间为 $\left[i_1, i_2\right]$, 那么最少行动次数为:
我们可以枚举 aliceIndex, 然后取所有结果的最小值。
1 | class Solution { |
参考文献
后记
首发于 silencezheng.top,转载请注明出处。