paizaオンラインハッカソン(略してpoh![ポー!])lite「天才火消しエンジニア霧島 もしpmおじさんが『丸投げ』を覚えたら」解説...

20
paizaオンラインハッカソン(略して POH![ポー!])Lite「天才火消しエン ジニア霧島 もしPMおじさんが『丸投 げ』を覚えたら」解説 ギノ株式会社 吉岡

Upload: paiza

Post on 22-Jul-2015

214 views

Category:

Software


3 download

TRANSCRIPT

Page 1: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投

げ』を覚えたら」解説

ギノ株式会社 吉岡

Page 2: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
Page 3: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

問題

https://paiza.jp/poh/kirishima

Page 4: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

問題• 人数(q)と費用(r)の組みがn個ある。

• 合計 m人 以上の組み合わせを探す。

• その中で最低の費用を出力する。

• 1≤n≤ 50 1≤q≤ 10,000 1≤r≤ 5,000,000 1≤m≤ 200,000

Page 5: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

解法1(全探索)

• 各社について、使う・使わないの全組み合わせを走査する。

• 合計がm人以上の組み合わせか判定する。

• その中で、一番小さい組み合わせを探す。

Page 6: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
Page 7: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

コード例1-1(全探索、再帰)

Page 8: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

@m  =  gets.to_i  @n  =  gets.to_i      @companies  =  []  @n.times{          q,  r  =  gets.split.map(&:to_i)          @companies.push([q,  r])  }      def  calc(i,  engineers,  cost)          if  i  ==  @n                  if  engineers  >=  @m                          return  cost                  else                          return  999999999999                  end          end                    ret1  =  calc(i+1,  engineers,  cost)          ret2  =  calc(i+1,  engineers+@companies[i][0],  cost+@companies[i][1])          return  [ret1,  ret2].min  end      puts  calc(0,  0,  0)

Page 9: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

コード例1-2 (全探索、ビット演算)10進数 2進数(0埋め3桁)

0 0001 0012 0103 0114 1005 1016 1107 111

Page 10: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

@m  =  gets.to_i  @n  =  gets.to_i      @companies  =  []  @n.times{          q,  r  =  gets.split.map(&:to_i)          @companies.push([q,  r])  }      mincost  =  99999999999  (0..2**@n).each{|i|          engineers  =  0          cost  =  0          (0...@n).each{|j|                  if  (i  &  (1<<j)  !=  0)  then                          engineers  +=  @companies[j][0]                          cost  +=  @companies[j][1]                  end          }          if  engineers  >=  @m                  mincost  =  [mincost,  cost].min          end  }  puts  mincost

Page 11: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

計算量• 計算量(Complexity)とは?

• O(x): 定数倍の差を無視した計算量

• O(g(n)) = {f(n): ある正の定数c, n0が存在して、すべてのn>n0に対して0≤f(n)≤cg(n)を満たす}

• アルゴリズムの効率の評価に多く使われる

Page 12: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

計算量• 各社、「使う」「使わない」の2通り

• 2^n通りの組み合わせ=> 2^n に比例した時間がかかる。=> 計算量: O(2^n)

• n=50なので、合計1,125,899,906,842,624通り

Page 13: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

効率は上げれないか?

Page 14: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

解法2 (動的計画法)

• 動的計画法とは問題を解いていく途中の結果を記録しておき、再利用することで効率を上げる方法

Page 15: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

解法2 (動的計画法)

• 最大人数をサイズとするメモ配列(DP[人数])を用意し、コストを記録していく。

• 各会社をループ

• 各メモ配列(DP)をループ

• DP[メモ配列の人数+会社の人数] =MIN(メモ配列のコスト + 会社のコスト, DP[メモ配列の人数+会社の人数])

Page 16: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
Page 17: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

コード

Page 18: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

m  =  gets.to_i  n  =  gets.to_i      dp  =  Array.new(m+1,  9999999999999)  dp[0]  =  0      n.times{          q,  r  =  gets.split.map(&:to_i)          m.downto(0).each{|i|                  q2  =  [i+q,  m].min                  dp[q2]  =  [dp[q2],  dp[i]+r].min          }  }      puts  dp[m]

Page 19: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

計算量

• 会社数(m) x 最大人数(n) がループ回数

• O(m x n)

• 最大ループ回数: 10,000,000 回

Page 20: paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説

参考

• 詳しくはblog『もし先輩女子エンジニアが『アルゴリズム』を図解で教えてくれるとしたら』http://paiza.hatenablog.com/entry/2014/09/11/%E3%82%82%E3%81%97%E5%85%88%E8%BC%A9%E5%A5%B3%E5%AD%90%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%8C%E3%80%8E%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%80%8F%E3%82%92%E5%9B%B3