20120127 nhn

1,304 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,304
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

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
  • 20120127 nhn

    1. 1. ∼シチュエーション別∼Perlでちょいモテアルゴリズム 2012/01/27 Livedoor DeNA 合同勉強会 萬野有生 @DeNA id: mandy_44
    2. 2. Case1:
    3. 3. Case1:「運命の人なら誕生日くらい当て られるよね!?9回で当てられ ないと・・・(*́ω`*)」
    4. 4. Case1:「運命の人なら誕生日くらい当て られるよね!?9回で当てられ ないと・・・(*́ω`*)」電波ですか?a(°Д°ill
    5. 5. 彼女の誕生日を9回以内に当てよ!ただしはずれると彼女は誕生日がそれより後か前か教えてくれる。
    6. 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. 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. 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. 9. Case2:
    10. 10. Case2:「私、1日でなるべくいっぱい映画 を見たいの☆(ゝω・)vキャピ」
    11. 11. Case2:「私、1日でなるべくいっぱい映画 を見たいの☆(ゝω・)vキャピ」DVD借りようよ(;・ ・)
    12. 12. n本の映画が上映されている。各映画は時刻siに始まりeiに終了する。できるだけ多くの映画を見たいとき何本見ることができるか。ただし途中入退場は出来ない。
    13. 13. 2 41 3 5 時間
    14. 14. 2 4 1 3 5 時間1.一番開始時間の早いものから見る2.一番時間の短いものから見る3.一番終了時間の早いものから見る
    15. 15. 2 4 1 3 5 時間 1.一番開始時間の早いものから見る 2.一番時間の短いものから見る 3.一番終了時間の早いものから見る今、その時点で一番○○なものを選んでいく
    16. 16. 2 4 1 3 5 時間 1.一番開始時間の早いものから見る 2.一番時間の短いものから見る 3.一番終了時間の早いものから見る今、その時点で一番○○なものを 貪欲法選んでいく
    17. 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. 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. 19. Case3:
    20. 20. Case3:「何でも食べていいんだよねっ? 何食べたら一番お腹いっぱいに なるかなー♪(・ ・)」
    21. 21. Case3:「何でも食べていいんだよねっ? 何食べたら一番お腹いっぱいに なるかなー♪(・ ・)」5万円まででお願いします (ヽ ω`)
    22. 22. n種類の料理のリストがある。各料理はpiの値段でviの量がある。X万円以内で一番量が多くなる料理の組み合わせを見つけよ。※ただし料理は1種類につき1回しか頼めない
    23. 23. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n)
    24. 24. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n) i番目の料理を食べる、食べない、に分解 食べた時 食べない時X-pi円でi番目以外の料 X円でi番目以外の料理で理で最も量を食べたい 最も量を食べたい
    25. 25. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n) i番目の料理を食べる、食べない、に分解 食べた時 食べない時X-pi円でi番目以外の料 X円でi番目以外の料理で理で最も量を食べたい 最も量を食べたい 動的計画法
    26. 26. i番目の料理を食べるか食べないかで総当たり → 計算量はO(2^n) i番目の料理を食べる、食べない、に分解 食べた時 食べない時X-pi円でi番目以外の料 X円でi番目以外の料理で理で最も量を食べたい 最も量を食べたい 動的計画法 一つ前や一つ後を考えたときに相似形が出てくる ような問題はDPで解きやすい!
    27. 27. i番目(i=0∼n-1)までの料理をj万円以内で食べた時の量の最大値をdp[i+1][j]とおくi→i+1とするときの遷移を考えると、以下の漸化式が導ける
    28. 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. 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. 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. 31. Case4:
    32. 32. Case4:「今度の旅行楽しみだねー♪でも 私最短距離で移動しないと怒っちゃうぞっ(o≧▽゚)o」
    33. 33. Case4:「今度の旅行楽しみだねー♪でも 私最短距離で移動しないと怒っ ちゃうぞっ(o≧▽゚)o」新幹線で(ry (;́ `)
    34. 34. n個の地点がある。各地点間の道路の距離が与えられた時、地点iから地点jまでの最短経路を求めよ。
    35. 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. 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. 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. 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. 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. 40. Thank you very much for your attention.

    ×