20120127 nhn
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
1,226
On Slideshare
1,224
From Embeds
2
Number of Embeds
1

Actions

Shares
Downloads
3
Comments
0
Likes
0

Embeds 2

http://a0.twimg.com 2

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 適用例はエレベーターとか\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 実用例としてカードゲームの最大コストに対する戦力の最大化、など\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • ダイクストラ法というものもあるが重みが負の時におかしくなる\nこれは無向グラフだったが有向グラフでもWFは適用可能\n実用例は乗り換え案内、など\n
  • \n

Transcript

  • 1. ∼シチュエーション別∼Perlでちょいモテアルゴリズム 2012/01/27 Livedoor DeNA 合同勉強会 萬野有生 @DeNA id: mandy_44
  • 2. Case1:
  • 3. Case1:「運命の人なら誕生日くらい当て られるよね!?9回で当てられ ないと・・・(*́ω`*)」
  • 4. Case1:「運命の人なら誕生日くらい当て られるよね!?9回で当てられ ないと・・・(*́ω`*)」電波ですか?a(°Д°ill
  • 5. 彼女の誕生日を9回以内に当てよ!ただしはずれると彼女は誕生日がそれより後か前か教えてくれる。
  • 6. 1/1 1/2 ・・・ 6/30 7/1 7/2 ・・・ 12/30 12/317/1 7/2 ・・・ 9/30 10/1 10/2 ・・・ 12/30 12/317/1 7/2 ・・・ 8/14 8/15 8/16 ・・・ 9/29 9/30
  • 7. #!/usr/bin/perluse strict;use warnings; 中間値を取ってきてそのmy $MAX_LOOP = 9; 前後どちらにあるか判定my $doy = 250; # 9/7my ($min $max) = (0, 365);my $ans;for (1..$MAX_LOOP) { 計算量はO(log2n)    my $mid = int(($min+$max)/2);    if ($mid == $doy) {        $ans = $mid; 並列N分探索は強力        last;    }    elsif($mid > $doy) {        $max = $mid;    }    else {        $min = $mid;    }}print "ans: ", $ans, "n";
  • 8. #!/usr/bin/perluse strict;use warnings; 中間値を取ってきてそのmy $MAX_LOOP = 9; 前後どちらにあるか判定my $doy = 250; # 9/7my ($min $max) = (0, 365);my $ans;for (1..$MAX_LOOP) { 計算量はO(log2n)    my $mid = int(($min+$max)/2);    if ($mid == $doy) {        $ans = $mid; 並列N分探索は強力        last;    }    elsif($mid > $doy) {        $max = $mid;    }    else {        $min = $mid; じわりじわりと攻めていく    }}print "ans: ", $ans, "n";
  • 9. Case2:
  • 10. Case2:「私、1日でなるべくいっぱい映画 を見たいの☆(ゝω・)vキャピ」
  • 11. Case2:「私、1日でなるべくいっぱい映画 を見たいの☆(ゝω・)vキャピ」DVD借りようよ(;・ ・)
  • 12. n本の映画が上映されている。各映画は時刻siに始まりeiに終了する。できるだけ多くの映画を見たいとき何本見ることができるか。ただし途中入退場は出来ない。
  • 13. 2 41 3 5 時間
  • 14. 2 4 1 3 5 時間1.一番開始時間の早いものから見る2.一番時間の短いものから見る3.一番終了時間の早いものから見る
  • 15. 2 4 1 3 5 時間 1.一番開始時間の早いものから見る 2.一番時間の短いものから見る 3.一番終了時間の早いものから見る今、その時点で一番○○なものを選んでいく
  • 16. 2 4 1 3 5 時間 1.一番開始時間の早いものから見る 2.一番時間の短いものから見る 3.一番終了時間の早いものから見る今、その時点で一番○○なものを 貪欲法選んでいく
  • 17. #!/usr/bin/perluse strict;use warnings; 終了時間でソート# 映画のリスト ↓my @movies = ([1,3], [2,5], [4,7], [6,9], [8,10]);@movies = sort { $a->[1] <=> $b->[1] } @movies; 順番に今見ることが出来my $ans = 0; るかを判定my $end = 0; # 前回見た映画の終了時刻 ↓for my $movie (@movies) {    if ($movie->[0] > $end) { 見れるものがあれば見る        $ans++;        $end = $movie->[1];    }} 計算量はO(n)print "ans: ", $ans, "n";
  • 18. #!/usr/bin/perluse strict;use warnings; 終了時間でソート# 映画のリスト ↓my @movies = ([1,3], [2,5], [4,7], [6,9], [8,10]);@movies = sort { $a->[1] <=> $b->[1] } @movies; 順番に今見ることが出来my $ans = 0; るかを判定my $end = 0; # 前回見た映画の終了時刻 ↓for my $movie (@movies) {    if ($movie->[0] > $end) { 見れるものがあれば見る        $ans++;        $end = $movie->[1];    }} 計算量はO(n)print "ans: ", $ans, "n"; 仕事も恋も貪欲さが大事
  • 19. Case3:
  • 20. Case3:「何でも食べていいんだよねっ? 何食べたら一番お腹いっぱいに なるかなー♪(・ ・)」
  • 21. Case3:「何でも食べていいんだよねっ? 何食べたら一番お腹いっぱいに なるかなー♪(・ ・)」5万円まででお願いします (ヽ ω`)
  • 22. n種類の料理のリストがある。各料理はpiの値段でviの量がある。X万円以内で一番量が多くなる料理の組み合わせを見つけよ。※ただし料理は1種類につき1回しか頼めない
  • 23. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n)
  • 24. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n) i番目の料理を食べる、食べない、に分解 食べた時 食べない時X-pi円でi番目以外の料 X円でi番目以外の料理で理で最も量を食べたい 最も量を食べたい
  • 25. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n) i番目の料理を食べる、食べない、に分解 食べた時 食べない時X-pi円でi番目以外の料 X円でi番目以外の料理で理で最も量を食べたい 最も量を食べたい 動的計画法
  • 26. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n) i番目の料理を食べる、食べない、に分解 食べた時 食べない時X-pi円でi番目以外の料 X円でi番目以外の料理で理で最も量を食べたい 最も量を食べたい 動的計画法 一つ前や一つ後を考えたときに相似形が出てくる ような問題はDPで解きやすい!
  • 27. i番目(i=0∼n-1)までの料理をj万円以内で食べた時の量の最大値をdp[i+1][j]とおくi→i+1とするときの遷移を考えると、以下の漸化式が導ける
  • 28. i番目(i=0∼n-1)までの料理をj万円以内で食 べた時の量の最大値をdp[i+1][j]とおく i→i+1とするときの遷移を考えると、以下の 漸化式が導ける dp[i][j] (j < v[i])dp[i+1][j] = max(dp[i][j], dp[i][j-p[i]]+v[i]) (それ以 外)
  • 29. #!/usr/bin/perluse strict;use warnings;use List::Util qw(max);my $n = 4; 計算量はたかだかO(nX)my @p = (2, 1, 3, 2);my @v = (3, 2, 4, 2);my $X = 5;my @dp = ([0, 0, 0, 0, 0, 0]);for my $i (0..$n-1) {    for my $j (0..$X) {        if ($j < $p[$i]) {            $dp[$i+1][$j] = $dp[$i][$j];        }        else {            $dp[$i+1][$j]                = max($dp[$i][$j], $dp[$i][$j-$p[$i]] + $v[$i]);        }    }}print "max_v: ", $dp[$n][$X], "n";
  • 30. #!/usr/bin/perluse strict;use warnings;use List::Util qw(max);my $n = 4; 計算量はたかだかO(nX)my @p = (2, 1, 3, 2);my @v = (3, 2, 4, 2);my $X = 5;my @dp = ([0, 0, 0, 0, 0, 0]);for my $i (0..$n-1) {    for my $j (0..$X) {        if ($j < $p[$i]) {            $dp[$i+1][$j] = $dp[$i][$j];        }        else {            $dp[$i+1][$j]                = max($dp[$i][$j], $dp[$i][$j-$p[$i]] + $v[$i]);        }    }}print "max_v: ", $dp[$n][$X], "n"; 過去の思い出は大切に
  • 31. Case4:
  • 32. Case4:「今度の旅行楽しみだねー♪でも 私最短距離で移動しないと怒っちゃうぞっ(o≧▽゚)o」
  • 33. Case4:「今度の旅行楽しみだねー♪でも 私最短距離で移動しないと怒っ ちゃうぞっ(o≧▽゚)o」新幹線で(ry (;́ `)
  • 34. n個の地点がある。各地点間の道路の距離が与えられた時、地点iから地点jまでの最短経路を求めよ。
  • 35. 3 2 9 8 10 41 11 12 この問題は左図のようなグラフで表される7 5 (この場合は重み付き無向グラフ) 6 1.n以下の整数kを取る 2.(1∼k) (i,j)のグラフを考える 3.この時のi,j間の最短経路をpi,jとする 4.このグラフに地点k+1を加える 5.この時のi,j間の最短経路は以下のどちらか
  • 36. 3 2 9 8 10 41 11 12 この問題は左図のようなグラフで表される7 5 (この場合は重み付き無向グラフ) 6 1.n以下の整数kを取る 2.(1∼k) (i,j)のグラフを考える 3.この時のi,j間の最短経路をpi,jとする 4.このグラフに地点k+1を加える 5.この時のi,j間の最短経路は以下のどちらか pi,jまたはpi,k+1+pk+1,j
  • 37. 3 2 9 ワーシャルフロイド 8 10 41 11 12 この問題は左図のようなグラフで表される7 5 (この場合は重み付き無向グラフ) 6 1.n以下の整数kを取る 2.(1∼k) (i,j)のグラフを考える 3.この時のi,j間の最短経路をpi,jとする 4.このグラフに地点k+1を加える 5.この時のi,j間の最短経路は以下のどちらか pi,jまたはpi,k+1+pk+1,j
  • 38. #!/usr/bin/perl $p[$i][$j]は、use strict;use warnings; 直通の道あり → 2点間の距離dmy $n = 12; 直通の道なし → (十分大きな数)my ($s, $g) = (2, 5);my @p = init_p(); $i == $j →0for my $k (1..$n) { で初期化する    for my $i (1..$n) {        for my $j (1..$n) {            if ($p[$i][$k] + $p[$k][$j] < $p[$i][$j]) {                $p[$i][$j] = $p[$i][$k] + $p[$k][$j];            }        }    }}print "ans: ", $p[$s][$g], "n"; 計算量はO(n^3)
  • 39. #!/usr/bin/perl $p[$i][$j]は、use strict;use warnings; 直通の道あり → 2点間の距離dmy $n = 12; 直通の道なし → (十分大きな数)my ($s, $g) = (2, 5);my @p = init_p(); $i == $j →0for my $k (1..$n) { で初期化する    for my $i (1..$n) {        for my $j (1..$n) {            if ($p[$i][$k] + $p[$k][$j] < $p[$i][$j]) {                $p[$i][$j] = $p[$i][$k] + $p[$k][$j];            }        }    }}print "ans: ", $p[$s][$g], "n"; 計算量はO(n^3) ときには遠回りも必要(?)
  • 40. Thank you very much for your attention.