给定符号N x M
的矩阵S
,并且给定的符号序列找到以给定顺序遍历所有符号的最小路径。允许的路线为UP, DOWN, LEFT, RIGHT
。
示例:
Matrix:
123
265
346
Sequence:
1234561
Output:
8 (start from top left corner, then D, D, R, R, U, L, U, L)
请注意,符号可以重复,因此图形算法在这里没用。 实际路径不相关,只有数字,因此动态编程可能就是这样。
形式上:给定的符号序列必须是路径的子序列。
我正在寻找一种能够找到上述最短路径长度的算法。
答案 0 :(得分:2)
动态编程状态可以是(row, col, pos)
:电路板上的两个坐标以及我们构建的序列中的位置。
函数f (row, col, pos)
是达到此状态所需的最小总距离。
显然,当matrix[row][col]
不等于sequence[pos]
时,状态无效。
我们将按f (row, col, pos) = infinity
对其进行编码。
对于f (row, col, 1) = 0
的位置,基数为matrix[row][col] = sequence[1]
。
外部循环遍历状态的pos
部分。
要在f (row, col, pos)
等于matrix[row][col]
的情况下查找sequence[pos]
,我们希望观察所有状态(row', col', pos - 1)
并采用f (row', col', pos - 1)
的最小值加上距离(row', col')
(row, col)
到|row - row'| + |col - col'|
。
此距离仅为f (row, col, n)
。
答案是n
的最小值,其中f (row, col, pos)
是序列的长度。
希望你能从这里拿走它。
即使实际路径相关,这种方法也会有所帮助。
为了找到实际路径,我们可以将先前的状态与函数值一起存储。
换句话说,row'
可以是三元组:实际答案,前一状态的col'
,前一状态的class Formatter {
...
virtual std::ostream& insert(std::ostream&) const = 0;
friend std::ostream& operator<<(std::ostream& os, const Formatter& fmt) {
return fmt.insert(os);
}
};
class Formatter_State1_Mode1: public Formatter {
...
std::ostream& insert(std::ostream&) const override;
};
class Formatter_State1_Mode2: public Formatter {
...
std::ostream& insert(std::ostream&) const override;
};
Formatter* makeFormatter(Mode, State, ...);
。
答案 1 :(得分:2)
当使用f(i, j)
矩阵中的s
实例时,i
代表实现序列前缀的最小距离j
,最长为s[i]
。角色f(i, j) = min(d(c, j') + f(i - 1, j'))
for all j'
where d is the distance function
c is the jth instance of the character s[i]
j' is an instance of the character s[i - 1]
。然后:
O(n * (r * c) * (r * c))
此解决方案的最大复杂度为n
,因为序列中有r * c
个字符,每个字符最多包含javac Flower.java -Xlint:unchecked
个实例。但对于输入而言,序列中每个字符的矩阵实例数量相对较少,可能会显着提高效率。