【发布时间】:2015-11-29 06:38:21
【问题描述】:
我需要制定一个算法来使用 BFS 解决这个问题: 给定一个有向加权图、一个起始节点、一个终止节点和一个整数 K,假设在起始和终止之间是否存在一条 wight 至少为 k 的路径。
所以,首先我声明了我的加权导向图类型,一个三元组列表:
type 'a graph = Gr of ('a * 'a * 'a) list;;
let grafo1 = Gr [(1,3,2);(1,1,5);(2,2,3);(5,5,3);(5,4,6);(3,1,6);(3,7,4);(6,2,7);(4,4,6)];;
在(x,y,z)中,x是起始节点,y是边权重,z是到达节点。
然后我做了一个succ函数:
let succ (Gr arcs) n=
let rec aux = function
[] -> []
| (x,y,z):: rest ->
if n = x then z::(aux rest)
else aux rest
in aux arcs;;
这个函数给我一个节点的后继作为输出,所以:
succ grafo1 1
给我
int list = [2; 5]
作为输出。
最后,我做了这个 bf_path 函数,它是一个修改后的 BFS,可以找到 2 个节点之间的路径(否则会引发异常),它需要 3 个输入:一个图形,谓词和起始节点
let bf_path g p start =
let rec aux visited = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then [x]
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
谓词指定条件,所以调用:
bf_path grafo1 ((=)7)1
给我int list = [1; 5; 6; 7] 作为输出,节点 1 和 7 之间的路径。
现在,我可以找到一条路径,但我需要找到一条 至少 权重 K 的路径,所以我做了一个小函数,它以三元组列表作为输入并将其相加重量值:
let rec tot = function
[] -> 0
|(v,c,p)::t -> c + (tot t);;
所以,调用并输出:
tot [(2,2,3);(4,5,6);(8,9,0)]
- : int = 16
我认为我需要的只是在函数中添加条件,所以我创建了这个函数,我添加了一个 int K 作为输入和一个条件:(tot path >= k)
let bf_path_final g p start k =
let rec aux visited = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then
if (tot [x]) >= k then [x]
else aux visited rest
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
函数编译没有问题:
val bf_path_final : ('a * int * 'b) graph ->
('a * int * 'b -> bool) -> 'a * int * 'b -> int -> ('a * int * 'b) list = <fun>
但是,当我尝试调用它时收到 错误:
bf_path_final grafo1 ((=)4)1,13;;
^^^^^^
Error: This expression has type int graph_w
but an expression was expected of type ('a * int * 'b) graph_w
那么,是函数错误还是我必须以其他方式调用它?
另一种解决方案是将函数 bf_path 输出(路径)作为我的 tot 函数的输入,但我的输出是一个列表int,而不是三元组列表,所以我尝试将我的第一个函数转换为三元组的输出:
(例如:而不是[1;5;6;7],它应该给出[(1,1,5);(5,4,6);(6,2,7)])
let bf_path_tr g p start =
let rec aux visited = function
[] -> raise Not_found
| (x,y,z)::rest -> if List.mem x visited then aux visited rest
else if p x then [(x,y,z)]
else try aux (x::visited) rest
with Not_found ->
(x,y,z):: aux (x::visited) (succ_w g (x,y,z))
in aux [] [start];;
同样的结果,函数编译完成
val bf_path_tr :
('a * 'b * 'c) graph ->
('a -> bool) -> 'a * 'b * 'c -> ('a * 'b * 'c) list = <fun>
但我得到同样的错误:
bf_path_tr grafo1 ((=)7)2
Characters 11-18:
bf_path_tr grafo1 ((=)7)2;;
^^^^^^
Error: This expression has type int graph
but an expression was expected of type ('a * 'b * 'c) graph
有什么想法可以解决这两个问题中的至少一个吗?
【问题讨论】: