下图是老师布置的一道题目,后面我用 ruby 实现了 A*
class AStar
def initialize edge
@edge = edge
@@h = { "A" => 9, "B" => 7, "C" => 6, "D" => 4, "E" => 2, "F" => 0 } #h[x] 表示x到终点的启发值
@open = [] #open[x][0]和open[x][1]分别表示一个顶点和其估价函数值
@closed = [] #closed[x]表示一个顶点
end
def set_open_and_closed vertex #vertex[0]和vertex[1]分别表示一个顶点和其评估函数值f
@edge.each { |from, to, g| @open << [to, vertex[1] - @@h[vertex[0]] + g + @@h[to]] if from == vertex[0] && !@closed.include?(to) }
@open.sort! { |x, y| y[1] <=> x[1] }
end
def show_the_road
current = ["A", 9]
loop do
set_open_and_closed(current)
puts "Current | vertex: #{current[0]}, open: #{@open}, closed: #{@closed}, f: #{current[1]}"
break if current[0] == "F" || @open.empty?
@closed << current[0]
current = @open.pop
end
end
end
edge = [["A", "B", 3], ["B", "A", 3], #edge[x][0]和edge[x][1]分别表示一条边的from和to, edge[x][2]为权值
["A", "C", 4], ["C", "A", 4],
["B", "D", 4], ["D", "B", 4],
["B", "E", 7], ["E", "B", 7],
["C", "D", 2], ["D", "C", 2],
["C", "E", 5], ["E", "C", 5],
["D", "E", 1], ["E", "D", 1],
["D", "F", 4], ["F", "D", 4],
["E", "F", 2], ["F", "E", 2]]
example = AStar.new(edge)
example.show_the_road
下面是结果
Current | vertex: A, open: [["B", 10], ["C", 10]], closed: [], f: 9
Current | vertex: C, open: [["E", 11], ["D", 10], ["B", 10]], closed: ["A"], f: 10
Current | vertex: B, open: [["E", 12], ["D", 11], ["E", 11], ["D", 10]], closed: ["A", "C"], f: 10
Current | vertex: D, open: [["E", 12], ["D", 11], ["E", 11], ["F", 10], ["E", 9]], closed: ["A", "C", "B"], f: 10
Current | vertex: E, open: [["E", 12], ["D", 11], ["E", 11], ["F", 10], ["F", 9]], closed: ["A", "C", "B", "D"], f: 9
Current | vertex: F, open: [["E", 12], ["D", 11], ["E", 11], ["F", 10]], closed: ["A", "C", "B", "D", "E"], f: 9
[Finished in 0.3s]
学习 ruby 不是很久,希望小伙伴们推荐更 rubyist 的写法。