動的計画法(1) ナップサック問題

1月 22nd, 2009 admin Posted in Ruby, アルゴリズムとデータ構造 | コメントは受け付けていません。

あと2問で終わりとなった「アルゴリズムとデータ構造シリーズ」です。今回は第11章「動的計画法」のナップサック問題です。

動的計画法

深さ優先探索や幅優先探索などの分割統治法(トップダウン的問題解決法)では指数的に計算量が増えてしまうような問題というのがあります。(本書では例として「43ペンスのお釣りを出すときに考えられる小銭の組合せ」という問題があげられていました)そのような問題を解決するひとつの方法としてあるのが動的計画法というもので、

全体をいくつかの小問題に分割して、先に一括して小問題の解をすべて得て、最終的にそれらを組み合わせて問題の解決に役立てる。

だそうです。いつもは自分の言葉で説明するのですが、このアルゴリズムは説明しにくい。理解してないということかもしれません・・・

コード

ナップサック問題というのを解く問題です

RUBY:
  1. class Product
  2.   attr_accessor :size, :value
  3.  
  4.   def initialize(size,value)
  5.     @size = size
  6.     @value = value
  7.   end
  8. end
  9.  
  10. products = [
  11.             Product.new(2,2),
  12.             Product.new(3,4),
  13.             Product.new(5,7),
  14.             Product.new(6,10),
  15.             Product.new(9,14)
  16.            ]
  17.  
  18. NAP_SIZE = 16
  19. NAP_SIZE_RANGE = 1..NAP_SIZE
  20. nap_value = Array.new.fill(0,0..NAP_SIZE)
  21.  
  22. printf("nap size            ");
  23. NAP_SIZE_RANGE.each do |j|
  24.   printf(" %2d",j)
  25. end
  26. puts "\n"
  27.  
  28. 0..products.size.times do |i|
  29.   NAP_SIZE_RANGE.each do |j|
  30.  
  31.     if j - products[i].size>= 0
  32.       new_value = (nap_value[j - products[i].size] || 0) + products[i].value
  33.     else
  34.       new_value = 0
  35.     end
  36.  
  37.     nap_value[j] = new_value if new_value> nap_value[j]
  38.   end
  39.  
  40.   printf("use product until #%d ", i+1);
  41.   NAP_SIZE_RANGE.each do |j|
  42.     printf("%2d ",nap_value[j])
  43.   end
  44.   puts "\n"
  45. end

まとめ

これを使うべきときに思い出せるかどうか不安。

※このシリーズは私がRubyでアルゴリズムとデータ構造を基礎から学ぶ記録です。全体の目次はこちらへ。

Comments are closed.