标签:
昨天我女朋友发了一个心理调查问卷要我做。我向来对这种形似心理调查问卷嗤之以鼻: 一个人的性格怎么可能由几个简单的问题决定。但作为技术人员,我决定用技术的手段分析这份调查问卷,向女朋友证明其缺乏科学性。
调查问卷的原版如下图
有兴趣的朋友可以玩玩~
我想了解如下几个问题:
1. 问卷是不是有环路?如果有环路,则可证明这份问卷不正规。
2. A 答案是不是不可能达到?因为4个答案中,只有A答案没有同的倾向。
3. 如果 A 答案能到达,那么有多少种可能?占比是多少?
这种问卷调查有特点:每一个题目都对应多个选项;每一个选项,都对应一个题目或者答案。从一个人答题的路径来看,其实这就是一个典型的图结构。
结合我想了解的问题,有如下几个方面需要考虑:
1. 证明图没有环路
2. 使用DFS证明A是可以达到的
3. 统计所有的可能的结果,算出A的占比
我打算使用 列表模式 构建图
@list = [
[1],
[2,3],
[3,4],
[4,5,6],
[5,6,7],
[6,7],
[7,8,9],
[8,9],
[9,10,11],
[10,11,12],
[12,13],
[13,14],
[13,15],
[15,18,14],
[15,18],
[16,18],
[17,18,19,20],
[20,21,‘B‘],
[19,‘C‘],
[22,‘A‘],
[21, ‘D‘],
[22, ‘B‘],
[‘A‘, ‘C‘, ‘D‘]
]
图的节点有 0 到 22, 再加上 A, B, C, D。
1. 因为我不想处理下标,所以图的起始位置,我设置成0;
2. 图的节点,我简单的用数组的下标表示;
3. 答案直接输出,不需要放在节点的集合中;
代码如下:
def has_cycle?
recursion_stack = [false] * 23
check_cycle(0, recursion_stack)
end
def check_cycle(vertex, recursion_stack)
recursion_stack[vertex] = true
@list[vertex].each do |node|
next if over?(node)
return true if recursion_stack[node]
check_cycle(node, recursion_stack)
end
recursion_stack[vertex] = false
return false
end
其中 over?
方法是用来判断递归是否结束。
def over?(point)
[‘A‘, ‘B‘, ‘C‘, ‘D‘].include?(point.to_s)
end
has_cycle
来判断是否有回路,我将一次完全迭代的节点是否访问到了的信息保存在recursion_stack
check_cycle
运行得出的结果是 false
@result = []
def dfs(node)
@list[node].each do |vertex|
if over?(vertex)
@result << vertex
next
end
dfs(vertex)
end
end
使用深度有限搜索, 将最后的结果保存在 @result
中,将结果打印出来。
def count_charactor(result, charactor)
result.count { |item| item == charactor }
end
dfs(0)
puts "一共有 %d 可能的答案" % @result.size
(‘A‘..‘D‘).to_a.each do |charactor|
puts "#{charactor}: %d 种可能, 占比为 %f" % [ count_charactor(@result, charactor), count_charactor(@result, charactor).to_f / @result.length]
end
结果如下:
一共有 27860 可能的答案
A: 8960 种可能, 占比为 0.321608
B: 3360 种可能, 占比为 0.120603
C: 8120 种可能, 占比为 0.291457
D: 7420 种可能, 占比为 0.266332
@i = 0
def dfs(node, stack)
stack.push node
@list[node].each do |vertex|
if over?(vertex)
@result << vertex
if vertex == ‘A‘
@i += 1
puts "到A的路径有:"
puts stack.join(" -> ")
end
break if @i == 100
next
end
dfs(vertex, stack)
end
stack.pop
end
用一个栈stack
来保存路径, 到A点将所有的结果输出
图的算法应用真的很广泛,值得深入研究。有时候将实时中的问题抽象成图的问题,能让我们从另外的一个角度看问题。再则,用ruby
实现图的算法也是很简单的。dfs
比bfs
简单,但收到程序栈的限制。但比较适合本程序。
标签:
原文地址:http://blog.csdn.net/hexudong08/article/details/51340504