为什么这种递归会产生重复的结果?

时间:2013-03-05 04:51:46

标签: ruby recursion

我想解决的问题如下:

  

鉴于n美元,你有无限的硬币,镍币,硬币和硬币   四分之一,计算代表n的方式的总数。

我想出了一个递归解决方案(让我们假设n是0.25美元所以输出不是一些荒谬的数字):

def changes(w, x, y, z)
  if 0.01 * w + 0.05 * x + 0.1 * y + 0.25 * z > 0.25
    return
  elsif 0.01 * w + 0.05 * x + 0.1 * y + 0.25 * z == 0.25
    @@counter += 1
    puts "w: #{w} x: #{x} y: #{y} z: #{z}"
  else
    changes(w + 1, x, y, z)
    changes(w, x + 1, y, z)
    changes(w, x, y + 1, z)
    changes(w, x, y, z + 1)
  end
end

@@counter = 0
changes(0, 0, 0, 0)
puts @@counter

基本上这里的想法是在匹配时递增计数器,否则尝试下一个可能的面额。

但在输出中有很多重复,如:

w: 15 x: 0 y: 1 z: 0
w: 15 x: 0 y: 1 z: 0
w: 15 x: 0 y: 1 z: 0
w: 15 x: 0 y: 1 z: 0
w: 15 x: 0 y: 1 z: 0
w: 10 x: 1 y: 1 z: 0
w: 15 x: 0 y: 1 z: 0
w: 10 x: 1 y: 1 z: 0

有人可以告诉我为什么吗?在我的递归中,我不总是传递具有不同值的参数吗?为什么多次打印相同的值?

谢谢。

2 个答案:

答案 0 :(得分:1)

仅举例说明如何获得重复

使用changes(0, 0, 0, 0)拨打电话。
它会失败并致电:

changes(1, 0, 0, 0) # a
changes(0, 1, 0, 0) # b
changes(0, 0, 1, 0) # c
changes(0, 0, 0, 1) # d
然后

a将失败并致电

changes(2, 0, 0, 0) # aa
changes(1, 1, 0, 0) # ab
changes(1, 0, 1, 0) # ac
changes(1, 0, 0, 1) # ad

同时,b将失败并致电

changes(1, 1, 0, 0) # ba
changes(0, 2, 0, 0) # bb
changes(0, 1, 1, 0) # bc
changes(0, 1, 0, 1) # bd

如您所见,abba使用相同的参数。等等ac / ca ...

答案 1 :(得分:0)

让我用一些解释重写你的代码:

@variants = []
def changes(w, x, y, z)
  case 0.01 * w + 0.05 * x + 0.1 * y + 0.25 * z 
  when 0...0.25
    changes(w + 1, x, y, z)
    changes(w, x + 1, y, z)
    changes(w, x, y + 1, z)
    changes(w, x, y, z + 1)
  when 0.25
    @variants << [w,x,y,z] unless @variants.include?([w,x,y,z])
  end 
end

changes(0, 0, 0, 0)
puts @variants.size
@variants.each { |v| puts "w: #{v[0]} x: #{v[1]} y: #{v[2]} z: #{v[3]}" }

您添加变量的主要想法是,如果且尚未计算。重复事实来自这样一个事实,即有不同的方式来达到州[w=1,x=1][0,0]⇒[0,1]⇒[1,1][0,0]⇒[1,0]⇒[1,1](注意中间链链接。)case在这里更明显而不是意大利面if-elsif-end