最小カットを使って「燃やす埋める問題」を解く

7,360 views

Published on

最小カットを使って「燃やす埋める問題」を解く方法について、問題とソースコードつきで、まとめました。ニコニコ生放送「TopCoderでプログラムしてみた」2000回記念放送の資料です。

Published in: Education
0 Comments
19 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,360
On SlideShare
0
From Embeds
0
Number of Embeds
885
Actions
Shares
0
Downloads
37
Comments
0
Likes
19
Embeds 0
No embeds

No notes for slide

最小カットを使って「燃やす埋める問題」を解く

  1. 1. 診断人(@nico_shindannin) 1
  2. 2. 1. 燃やす埋める問題とは 2. 基本 3. 選択肢をうまく並べる 4. 二部グラフの性質を生かす 5. 複雑な制約条件を入れる 6. 最小カットの復元をする 7. 費用を工夫して割り当てる 2
  3. 3. 2. 燃やす埋める問題 引用:Komakiさんのページ http://topcoder.g.hatena.ne.jp/CKomaki/20121019/1350663591 3. FoxAndGo3 引用:TopCoder - SRM594 Div1 Medium http://community.topcoder.com/stat?c=problem_statement&pm=12808&rd=15706 4. The Year of Code Jam 引用:Google Code Jam World Finals 2008 E (プログラミングコンテストチャレンジブック P357) https://code.google.com/codejam/contest/32011/dashboard#s=p4 5. Surrounding Game 引用:TopCoder - SRM558 Div1 Hard https://code.google.com/codejam/contest/32011/dashboard#s=p4 6. 1 引用: 立命館合宿2013 Day2 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2496 7. RabbitWorking 引用: TopCoder - SRM 542 Div1 Hard http://community.topcoder.com/stat?c=problem_statement&pm=11054&rd=14734 3
  4. 4. 4
  5. 5. 燃やす埋める問題 引用:Komakiさんのページ http://topcoder.g.hatena.ne.jp/CKomaki/20121019/1350663591 A,B,Cは「燃やす」か「土に埋める」必要がある。 ◦A,B,Cは「燃やす」とそれぞれ50,60,130円もらえる。 ◦A,B,Cは「土に埋める」と100円もらえる。 ◦BとCの片方だけ「燃やす」と死ぬ。 死なずに最高で何円もらえるか? 5
  6. 6. 複数の小問題がある ◦それぞれの小問題に対し選択肢がある ◦選択肢ごとに、費用・利益がある 選択肢同士に依存関係もありうる ◦小問題1で選択肢Aを選んだら、小問題3でAは選べない。 ◦小問題1も小問題2でも選択肢Aを選んだ時は罰金として 費用がかかる。 全体の費用を最小化(利益を最大化)する 6
  7. 7. 複数の小問題(20問以下) がある。 ◦それぞれの小問題に対し選択肢(Selection)がある ◦選択肢ごとに、費用・利益がある 選択肢同士に依存関係もありうる ◦小問題1で選択肢Aを選んだら、小問題3でAは選べない。 ◦小問題1も小問題2でも選択肢Aを選んだ時は罰金として 費用がかかる。 全体の費用を最小化(利益を最大化)する これなら総当たりで解けます 計算量は20*220 しかし、問題が増えるとO(n*2n)なので解けない。 7
  8. 8. 複数の小問題がある。 ◦それぞれの小問題に対し選択肢がある ◦選択肢ごとに、費用・利益がある 選択肢同士に依存関係もありうる ◦小問題1で選択肢Aを選んだら、小問題3でAは選べない。 ◦小問題1も小問題2でも選択肢Aを選んだ時は罰金として 費用がかかる。 全体の費用を最小化(利益を最大化)する これなら、小問題ごとに独立しているので それぞれの小問題の費用を最小化して足せばいい。 しかし、依存関係があると全体の費用を最小化 できない 8
  9. 9. 複数の小問題(10000問とか)がある ◦それぞれの小問題に対し選択肢がある ◦選択肢ごとに、費用・利益がある 選択肢同士に依存関係もありうる ◦小問題1で選択肢Aを選んだら、小問題3でAは選べない。 ◦小問題1も小問題2でも選択肢Aを選んだ時は罰金として 費用がかかる。 全体の費用を最小化(利益を最大化)する これを最小カットで解きます。 9
  10. 10. 10
  11. 11. 11 燃やす埋める問題 Super Easy A,B,Cは「燃やす」か「土に埋める」必要がある。 ◦A,B,Cは「燃やす」とそれぞれ50,60,130円かかる。 ◦A,B,Cは「土に埋める」と100円かかる。 最小で何円かかるか?
  12. 12. 燃やす埋める問題 Super Easy A,B,Cは「燃やす」か「土に埋める」必要がある。 ◦A,B,Cは「燃やす」とそれぞれ50,60,130円かかる。 ◦A,B,Cは「土に埋める」と100円かかる。 最小で何円かかるか? 12 それぞれ、金額の安い選択肢を選べばよい。 ◦Aを「燃やす」Bを「燃やす」Cを「土に埋める」 ◦50+60+100=210円が最小
  13. 13. 13 s A B t C 50 60 130 100 100 100 燃やす 燃やす 燃やす 土に埋める 土に埋める 土に埋める 頂点sから頂点tへ辺をつなげる。 ◦小問題ごとに並列につなげる ◦選択肢は直列につなげる
  14. 14. 14 s A B t C 50 60 130 100 100 100 燃やす 燃やす 燃やす 土に埋める 土に埋める 土に埋める 最小s-tカットは、このようになる。 ◦最小で50+60+100=210でs→tがつながらなくなる。 ◦カット(赤い線)した部分が、小問題の選択肢になる。
  15. 15. 15 s A B t C 50 60 130 100 100 100 燃やす 燃やす 燃やす 土に埋める 土に埋める 土に埋める 最小s-tカットは、このようになる。 ◦最小で50+60+100=210でs→tがつながらなくなる。 ◦カットした部分が、小問題の選択肢になる。
  16. 16. s-tカットなので、t->sは無視してよい 有向グラフです 切るところは、平面図的につながってなくてよい s側とt側の2つに切る。3つ切ってはいけない。 元のグラフはs->tへの経路が存在する必要がある 16
  17. 17. 最小カットをプログラムで計算するのは困難 最小s-tカット=最大s-tフロー ◦最小カットの各辺のコストが、最大フローの容量になる 最大フローを求めるのにはDinic法を使う O(EV2)だが、実際はもっと速いので、おすすめ 17 s A B t C 50/50 60/60 100/130 50/100 60/100 100/100 流量/容量
  18. 18. http://ideone.com/rwECrx グラフを構築する部分はmain関数にあります。 コードの最後の方をみてください。 頂点0,1,2が頂点A,B,Cに対応しています。 18
  19. 19. 19 燃やす埋める問題 Very Easy A,B,Cは「燃やす」か「土に埋める」必要がある。 ◦A,B,Cは「燃やす」とそれぞれ50,60,130円もらえる。 ◦A,B,Cは「土に埋める」と100円もらえる。 最大で何円もらえるか?
  20. 20. 20 燃やす埋める問題 Very Easy A,B,Cは「燃やす」か「土に埋める」必要がある。 ◦A,B,Cは「燃やす」とそれぞれ50,60,130円もらえる。 ◦A,B,Cは「土に埋める」と100円もらえる。 最大で何円もらえるか? 最小カットは、最小値を求める。最大値ではない。 そこで、最小値を求める問題に置き換える!
  21. 21. 21 燃やす 土に埋める A 50円の利益 100円の利益 B 60円の利益 100円の利益 C 130円の利益 100円の利益 無条件で得られる利益 燃やす 土に埋める A 100円の利益 50円の損失 0円の損失 B 100円の利益 40円の損失 0円の損失 C 130円の利益 0円の損失 30円の損失 利益が大きい選択肢の利益を、無条件で得られるこ とにする→その分選択肢からひくと全て損失に
  22. 22. 22 燃やす 土に埋める A 50円の利益 100円の利益 B 60円の利益 100円の利益 C 130円の利益 100円の利益 これはダメ! ◦負辺があるときの最小カット問題はNP困難 燃やす 土に埋める A -50円の損失 -100円の損失 B -60円の損失 -100円の損失 C -130円の損失 -100円の損失
  23. 23. s A B t C 50 40 0 0 0 30 燃やす 燃やす 燃やす 土に埋める 土に埋める 土に埋める 最小s-tカットは0+0+0=0 あらかじめ貰える利益は100+100+130=330 求める最大値は330-0=330
  24. 24. s A B t C 50 40 0 0 0 30 燃やす 燃やす 燃やす 土に埋める 土に埋める 土に埋める コスト0の辺もグラフに書きましょう! ◦最小カット問題のグラフでは、 辺が元からないのと、損失0の辺とでは、別物です。 ◦最大フローを求めるときに、容量0になるのでいらない辺に なりますが、それでも書きましょう ◦複雑な問題だと、辺が元からないのか、辺があるけどコスト が0なのかで、混乱しやすくなる。
  25. 25. http://ideone.com/WgGXlL 25
  26. 26. 26 燃やす埋める問題 Easy A,Bは「燃やす」か「土に埋める」必要がある。 ◦A,Bは「燃やす」とそれぞれ20,100円かかる。 ◦A,Bは「土に埋める」とそれぞれ50,20円かかる。 ◦Aを燃やしたときに、Bを土に埋めると罰金300円かかる。 最小で何円かかるか?
  27. 27. 27 s A B t 20 100 50 20 燃やす 燃やす 土に埋める 土に埋める Aを燃やしたときにBを土に埋めると 罰金300円かかる
  28. 28. 28 s A B t 20 100 50 20 燃やす 燃やす 土に埋める 土に埋める Aを燃やしたときにBを土に埋めると 罰金300円かかる Aを燃やしたときにBを土に埋めたら まだs-tカットが成立しないようにする
  29. 29. 29 s A B t 20 100 50 20 燃やす 燃やす 土に埋める 土に埋める Aを燃やしたときにBを土に埋めると 罰金300円かかる Aを燃やしたときにBを土に埋めたら まだs-tカットが成立しないようにする 300 罰金
  30. 30. 30 s A B t 20 100 50 20 燃やす 燃やす 土に埋める 土に埋める こうすると、s-tカットするにはB→Aの辺をカッ トせざるをえない。つまり300円かかる。 もちろん、これは最小カットではない。 この制約条件の追加方法を理解できないと その後すべて理解できなくなるので注意! 300 罰金
  31. 31. 31 s A B t 20 100 50 20 燃やす 燃やす 土に埋める 土に埋める 両方を土に埋めると最小カット70円になります。 300 罰金
  32. 32. http://ideone.com/OlgYjD 32
  33. 33. 1.小問題を並列に、選択肢を直列に並べて、グラ フを作る。 2.最大化する問題は、考えうる最大の利益をあら かじめ得てることにして、最小化問題に置き換 える。 3.制約条件を入れるときは、ある選択肢の組み合 わせを選んだ時に、そのままではs-tカットがで きないように、辺を追加する。 33
  34. 34. 34
  35. 35. 35 s A B t C 50 60 130 100 100 100 燃やす 燃やす 燃やす 土に埋める 土に埋める 土に埋める 選択肢はどういう順番に置いてもよい。 ◦ただ、順番が悪いと、制約条件を追加できないことが ある。 考えて選択肢の順番を決めないといけない。
  36. 36. 36 FoxAndGo3 引用:TopCoder - SRM594 Div1 Medium http://community.topcoder.com/stat?c=problem_statement&pm=12808&rd=15706 囲碁っぽい問題。自分が黒番で好きなだけ黒石を 置ける。(死ぬ場所にも置けるので注意) 黒石で白石のまわりを隙間なく囲めば白石を除い て領地(=空きマス)にすることができる。 領地の最大値を求めよ。 盤面の数は最大で50*50。また、白石同士は隣接 していない。
  37. 37. 37 そのまま置かなければ、領地は24 ◦本物の囲碁と違います
  38. 38. 38 黒石を置けば、白石がとれるけど、置いた分だけ 領地が21に減る。何もおかないほうが領地が24 で最大。
  39. 39. 39 このままでは領地は1
  40. 40. 40 黒石を真ん中に置くと、すべての白石が死に、自 分の領地になる。領地は4、これが最大値。
  41. 41. 41 初期の領地は10ですが、黒をうまく置くと、 最大領地は12になるようです。
  42. 42. 42 最大値を求める問題なので、このままでは 最小カットが使えない。 ◦黒石が最初からおいてあるところは絶対領地にできない ◦つまり、仮の最大領地数=盤面の全マスー黒石数 ◦そこから逆に以下のように考える 白石がとれなかったら、領地1の損失 領地(空きマス)で黒石をおいたら、領地1の損失 ◦仮の最大領地数ー最小の領地損失=最大の領地数で求め ることができる。
  43. 43. 43 s t 1 0 1 0 1 0 黒置く 白死領地 黒置く 領地 白のまま 黒石は無視してよい。選択肢がないから。 領地を1の損失と考えたこのグラフは正しい。 「白死領地にするには、まわりに黒を置かない といけない」の制約をどうするか? 領地 白石と隣接する領地 (空きマス) 白石
  44. 44. s t 1 0 1 0 1 0 黒置く 白死領地 黒置く 領地 白のまま 領地 この2つを強制的に切らせたい
  45. 45. s t 1 0 1 0 1 0 黒置く 白死領地 黒置く 領地 白のまま 領地 +∞ +∞
  46. 46. s t 1 0 1 0 1 0 黒置く 白死領地 黒置く 領地 白のまま 領地 +∞ +∞ +∞の制約条件を入れても、最小カットが成立 してしまう。「黒置く」のところを強制的に カットさせたいのにできない。 +∞のリンクを逆にしても、同じ。
  47. 47. 47 s t 0 0 0 1 1 1 領地 白死領地 領地 黒置く 白のまま 「黒置く」と「領地」の選択肢の順番を変える 黒置く
  48. 48. 48 s t 0 0 0 1 1 1 領地 白死領地 領地 黒置く 白のまま +∞の辺を白から領地の方向へ足す 黒置く +∞ +∞
  49. 49. 49 s t 0 0 0 1 1 1 領地 白死領地 領地 黒置く 白のまま 黒置く +∞ +∞ こうすると、領地の辺をカットしても、 まだs-tは繋がっている。最小s-tカットになってい ないので、解にならない。 ◦つまり、元からの領地の部分に黒石をおかないのであれば、 白石を殺して領地にすることはできないという意味。
  50. 50. 50 s t 0 0 0 1 1 1 領地 白死領地 領地 黒置く 白のまま 黒置く +∞ +∞ 仮に隣接する1カ所をカットしても まだs-tは繋がっている
  51. 51. 51 s t 0 0 0 1 1 1 領地 白死領地 領地 黒置く 白のまま 黒置く +∞ +∞ つまり、隣接する領地は、すべて「黒置く」を選ば ないと、s-tカットできない。 「白石を殺して領地にするには、まわりに黒を置か ないといけない」という制約通りになってる。
  52. 52. 52 s t 0 0 0 1 1 1 領地 白死領地 領地 黒置く 白のまま 黒置く +∞ +∞ うっかり+∞の辺を領地から隣接する白方向に 足すと、うまくいかない。 上の例で、「黒置く」をカットしなくても、s-t カットができている。
  53. 53. 53 s t 0 0 0 1 1 1 領地 白死領地 領地 黒置く 白のまま 黒置く +∞ +∞ うっかり+∞の辺を領地から隣接する白方向に 足すと、うまくいかない。 上の例で、「黒置く」をカットしなくても、s-t カットができている。
  54. 54. 54 FoxAndGo3 引用:TopCoder SRM594 Div1 Medium http://community.topcoder.com/stat?c=problem_statement&pm=12808&rd=15706 囲碁っぽい問題。自分が黒番で好きなだけ黒石を 置ける。(死ぬ場所にも置けるので注意) 黒石で白石のまわりを隙間なく囲めば白石を除い て領地(=空きマス)にすることができる。 領地の最大値を求めよ。 盤面の数は最大で50*50。また、白石同士は隣接 していない。←この条件があると、囲む判定を工 夫する必要がありますが、それでも解けます。
  55. 55. 55
  56. 56. 56 The Year of Code Jam 引用:Google Code Jam World Finals 2008 E (プログラミングコンテストチャレンジブック P357) https://code.google.com/codejam/contest/32011/dashboard#s=p4 カレンダーN月で、各月はM日。 ◦白:コンテストが開かれない日 ◦青:コンテストに参加する日 ◦?:コンテストが開かれるが、参加しようか迷っている日 1つのコンテストに参加すると ◦幸福度の初期値は4 ◦カレンダー上で隣接する日に参加するコンテスト1つにつき幸 福度は1下がる 幸福度の最大値を求めなさい。 1≦N≦50, 1≦M≦50
  57. 57. 57 青が4点。青同士が隣合うと-1点。 最高点がとれるように?の色を青か白にせよ。
  58. 58. 58 最大値問題から最小値問題への置き換えをする。 ◦?のマスは元から4点取ってることにする。 ◦?を白にしたら、4点減点。 s t 4 0 白にする 青にする ?
  59. 59. 59 ?と隣接する青マスに対して、 ◦?が青になったときは、1点減点 ◦?が白になったときは、何もしない s t 4 0 白にする 青にする ?
  60. 60. 60 sから青マスへ+∞の辺をつなげる。 ◦+∞の辺を、s,tのどちら側につなげても良いが、制約条 件を考えること。 今回のようにsと青マスをつないだ場合は、青マ スから?へコスト2を足すとよい。 ◦青マス、?マスの両方でコスト1ずつ損するので、コス ト2になる。 s t 4 0 白にする 青にする ? +∞ 2
  61. 61. 61 ?-?間の制約条件 s t 4 0 白にする 青にする ? ? 青にする 0 白にする 4
  62. 62. 62 ?を両方青にしても、s-tカットできる。 ◦コスト2を課すことができない。 s t 4 0 白にする 青にする ? ? 青にする 0 白にする 4 2
  63. 63. 63 逆向きにしても、s-tカットできるのでダメ。 s t 4 0 白にする 青にする ? ? 青にする 0 白にする 4 2
  64. 64. 64 両向きにしても、s-tカットできるのでダメ。 s t 4 0 白にする 青にする ? ? 青にする 0 白にする 4 2
  65. 65. 65 グリッドグラフは二部グラフである。 ◦EVEN同士とODD同士がつながることはない。 マスをEVENとODDで区別すれば、先ほどの問題 は解決できる EVEN:(x+y)%2==0 ODD:(x+y)%2==1
  66. 66. 66 ◦ODDのマスに対して、3章で学んだ、選択肢を並べ替え るテクニックを使う ◦このようにすると、両方とも青にするをカットしても、 s-tカットにならない。コスト2の辺もカットする必要が ある。 s t 4 4 白にする 青にする ? ? 白にする 0 EVEN ODD 0 青にする 2
  67. 67. 67 s t 4 4 白にする 青にする ? ? 白にする 0 EVEN ODD 0 青にする 2 +∞ 2 ODD EVEN 2 +∞ ◦ODD側の青マスからt側に+∞の辺を足す。 これでグラフが完成です。
  68. 68. http://ideone.com/wsv2RY プログラミングコンテストチャレンジブックでは 白マスもでてきますが、必要ありません。 68
  69. 69. 69
  70. 70. 70 Surrounding Game 引用:TopCoder - SRM558 Div1 Hard https://code.google.com/codejam/contest/32011/dashboard#s=p4 長方形の盤面(最大20マス*20マス)があり、す べてのマスに利益biと費用ciが割り当てられてい る。 ◦マスに石を置くか、全ての隣接するマスに石を置くと、 利益biが得られる。 ◦マスに石を置くと、費用ciがかかる スコア=全利益-全費用とする。スコアを最大化 せよ。
  71. 71. 71 b0=3 c0=8 b1=7 c1=1 b2=4 c2=9 b3=5 c3=1 b4=7 c4=6 b5=9 c5=5 b6=5 c6=3 b7=7 c7=2 b8=1 c8=0
  72. 72. 72 b0=3 c0=8 b1=7 c1=1 b2=4 c2=9 b3=5 c3=1 b4=7 c4=6 b5=9 c5=5 b6=5 c6=3 b7=7 c7=2 b8=1 c8=0 置いた場所の利益b1=7、置く損失c1=1 ◦つまり、スコアは、7-1=6
  73. 73. 73 b0=3 c0=8 b1=7 c1=1 b2=4 c2=9 b3=5 c3=1 b4=7 c4=6 b5=9 c5=5 b6=5 c6=3 b7=7 c7=2 b8=1 c8=0 b4のように囲んだ場所の利益も得られる。 ◦スコアは、b1-c1+b3-c3+b5-c5+b7-c7+b4=26
  74. 74. 74 b0=3 c0=8 b1=7 c1=1 b2=4 c2=9 b3=5 c3=1 b4=7 c4=6 b5=9 c5=5 b6=5 c6=3 b7=7 c7=2 b8=1 c8=0 囲むか置くかで点が得られる。b4のように囲んだ場所 に置いても、利益が2倍得られたりしないので注意! スコアは、b1-c1+b3-c3+b5-c5+b7-c7+b4-c4=20
  75. 75. 制約条件が難しいので、まずは、1マスだけ考え る ◦マスに石を置くか、全ての隣接するマスに石を置くと、 利益が得られる。→ OR の条件がやっかい ◦マスに石を置くと、費用がかかる。 75
  76. 76. 76 まず、選択肢として、置く・置かないはある 最小値問題にする ◦bi-ci>0のとき、元からbi-ciのもらえてるとすれば、置い たときはコスト0、置かないときはbi-ci s t 置く 0 置かない bi-ci
  77. 77. 77 まず、選択肢として、置く・置かないはある 最小値問題にする ◦bi-ci<0のとき、損失するか0のままなので、置いたとき はコストci-bi、置かないときは0 s t 置く ci-bi 置かない 0
  78. 78. 78 ここから先はbi-ci>0ときだけのグラフを書きます。 ◦bi-ci>0でもci-bi>0でも、グラフの形はかわらず、コス トが違うだけ。あまり影響はない。
  79. 79. 79 他に、囲まれる・囲まれないという状態もある。 1つのマスごとに、2つの頂点を使えば、良いのでは ないか? 囲む・囲まれないは、元からbiもらえてることにする。 これでいいの? s 置 く t 置く 置かない 0 囲 む 囲まれない bi 囲まれる 0 bi-ci
  80. 80. 80 これはダメ。 「置く」かつ「囲まれる」でs-tカットできる ◦「置く」かつ「囲まれる」で利益の2重どり(2bi-ci)に なってしまう。 s 置 く t 置く 置かない bi-ci 0 囲 む 囲まれない bi 囲まれる 0
  81. 81. 81 「囲む」から「置く」へコスト+∞の辺を追加 「置く」かつ「囲まれる」は許されなくなる。 ◦もとから無意味な状態(「囲まれる」場所に「置く」メ リット)はないので、強制的に除外しても構わない。 s 置 く t 置く 置かない bi-ci 0 囲 む 囲まれない bi 囲まれる 0 +∞
  82. 82. 82 s 置 く t 置く 置かない bi-ci 0 囲 む 囲まれない bi 囲まれる 0 +∞ EVEN (偶数マス) ODD (奇数マス) 置 く 置く 置かない bi-ci 0 囲 む 囲まれない bi 囲まれる 0 +∞ 「囲まれるには、周り全てに置く必要がある」 の制約条件を入れる準備として、奇数ODDマスの選択 肢をすべて逆にする。
  83. 83. 83 s 置 く t 置く 置かない bi-ci 0 囲 む 囲まれない bi 囲まれる 0 +∞ 置 く 置く 置かない bi-ci 0 囲 む 囲まれない bi 囲まれる 0 +∞ EVEN (偶数マス) ODD (奇数マス) 「囲まれる」とき「隣に置かない」のは禁止なので これらを選んだ時にs-tカットができないように+∞ の辺を貼ればよい。 +∞ +∞
  84. 84. http://ideone.com/9kZXjO 84
  85. 85. 85
  86. 86. 86 1 引用: 立命館合宿2013 Day2 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2496 長さnのビット列がある. ◦左からi番目のビットが1のとき,スコアをai点得られる. ◦左からi番目のビットを中心に距離w以内にある1の個数 (=|{j∈{1,…,n}∩{i-w,…,i+w}|左からj番目のビットが1}|) が奇数のとき,スコアをbi点得られる. スコアを最も多く得られるようなビット列を求め よ.
  87. 87. 公式の解説もぜひ参考にしてください。 http://www.slideshare.net/oupc/h1- 17155052 87
  88. 88. 各ビットごとに、2つの得点aiとbiがある。 88 ????????? ai 8 2 3 4 2 4 5 7 1 bi 1 3 9 7 1 5 5 8 6 w=2 ビット列
  89. 89. ビットが1のところは、ai点得られる。 89 110111011 ai 8 2 3 4 2 4 5 7 1 bi 1 3 9 7 1 5 5 8 6 w=2 ビット列
  90. 90. w=2なので、範囲[i-2,i+2]の間のビット1の数 が奇数なら、bi点得られる。 90 110111011 ai 8 2 3 4 2 4 5 7 1 bi 1 3 9 7 1 5 5 8 6 w=2 ビット列 234434432 ビット列[i-2,i+2] 1が3個
  91. 91. この場合、合計点は、 8+2+4+2+4+7+1+3+1+8=40点 最大得点となるときの、ビット列を求める問題 ◦最大得点を求める問題ではない。 91 110111011 ai 8 2 3 4 2 4 5 7 1 bi 1 3 9 7 1 5 5 8 6 w=2 ビット列 234434432 ビット列[i-2,i+2]
  92. 92. これまでの問題のように、グラフをつくれるが… ◦ビット1かビット0かの選択。元からai点もらえること にしておいて、ビット0のときに損失ai点となるように する。 「距離w以内にある1の個数が奇数のときbi点」の 条件の追加が難しい。 ◦グラフで考えたら、「ビット1を選択したカットの数を 数える」という処理が必要になり、たぶん不可能。 92
  93. 93. ビット列の累積和(mod2)を決める問題とみな す。 累積和が分かれば、範囲の和は求められる。 ◦ビットiをk[i]とする。 ◦ビット0~iの累積和をx[i+1]=k[0]+k[1]+…+k[i]とす る。(x[0]=0) ビットiの値 k[i]=x[i+1]-x[i] ビットl~rの総和 k[l]+k[l+1]+...+k[r]=x[r+1]-x[l] ビットi-w~i+wの総和 x[i+w+1]-x[i-w] 93 x[0] x[1] x[2] x[3] +k[0] +k[1] +k[2] 0 k[0] k[0]+k[1] k[0]+k[1]+k[2]
  94. 94. 累積和xを使えば、制約条件も簡単になる。 ◦x[i+w+1]-x[i-w]=1ならbi点 mod2なので、奇数個なら1 ◦x[i+1]-x[i]=1ならai点 2つの項の関係なら、最小カット用のグラフに、 制約条件いれることが簡単にできる。 94
  95. 95. あらかじめai,bi全ての得点をもらえたことにして、 最小化問題に置き換える。 端の処理が難しいので、前後にw個の番兵をいれ る。番兵の部分は範囲外で、ビット1を数えると きに影響を与えないようにしたいので、ビット0 とする。 ◦k={0.....0??.......??0.....0} 95 w個 w個 n個
  96. 96. 累積和xは、先ほどのページのように、x[0]=0の 分、1要素増える。 また、後ろの番兵の処理は、要注意。元のビット の最後の要素が続くことになる。 ◦なぜなら、0を足すかぎり、累積和は変わらないので。 つまり、2パータン試す必要がある。 ◦x={0......0??.......?00.....0} または ◦x={0......0??.......?11.....1} 96 w+1個 w個 n個 w+1個 w個 n個 元のビットの部分だけど(番兵ではない) 値が決まっているのに注意。
  97. 97. 97 次のページからのグラフはn=4、w=1のケースで す。
  98. 98. 98 まず、選択ができるビットについて考える。 ◦x[i+1]-x[i]=1(mod2)で得点ai-wの制約条件を入れたい。 得点aもx[i+1]-x[i]=0のとき減点ai-wの最小化とみなす ◦つまり隣合うx[i+1]とx[i]が同じ値なら、コストai-wをカット させるようにすればいい。→このグラフでは無理! s x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 0にする 0にする 0にする 1にする 1にする 1にする 1にする 注意:これらの辺は すべてコスト0です。 (狭いので文字は省略)
  99. 99. 99 x[奇数]の選択肢を入れ替えて、制約の双方向リンク を足す。 ◦たとえばx[2],x[3]に着目すると、 x[2]を0にする,x[3]を0にするとき、a1をカットしないといけない。 x[2]を1にする,x[3]を1にするとき、a1をカットしないといけない。 ◦これでコストaiをグラフに追加できた。 s x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 1にする 0にする 1にする 0にする a3 a2 a1 a0
  100. 100. 100 s x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 1にする 0にする 1にする 0にする a3 a2 a1 a0 biについても同様。 ◦x[i+w+1]-x[i-w]=1(mod2)で得点bi-wの制約条件を入れたい。 ◦x[i+w+1]-x[i-w]=0のとき減点bi-wの最小化とみなす 奇数個(2*w+1)離れるところの頂点を結ぶので、このグ ラフにうまく足せる。(偶数個ならこの問題は解けな い。) b0 b1 b2 b3
  101. 101. s a0 101 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 1にする 0にする 1にする 0にする a3 a2 a1 番兵の部分の辺を考える。 ◦x[0],x[1]は、ビット0固定 ◦右側の番兵・1固定の部分を考える。 b0 b1 b2 b3
  102. 102. 102 0にする、1にするは交互に並べないといけない のは同じ。 s a0 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 1にする 0にする 1にする 0にする a3 a2 a1 b0 b1 b2 b3 1にする 0にする 1にする 0にする 0にする 1にする
  103. 103. s 103 a0 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 1にする 0にする 1にする 0にする a3 a2 a1 b0 b1 b2 b3 1にする 0にする 1にする 0にする 0にする 1にする 0固定のビット ◦「0にする」をすでに選択した(=カットした)とみな すので、辺は不要。
  104. 104. s 104 0固定のビット ◦「0にする」をすでに選択した(=カットした)とみな すので、辺は不要。「1にする」は、もうカットできな いので、+∞の辺にする。 a0 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 1にする 0にする 1にする 0にする a3 a2 a1 b0 b1 b2 b3 1にする 0にする +∞ +∞
  105. 105. 累積和xは、先ほどのページのように、x[0]=0の 分、1要素増える。 また、後ろの番兵の処理は、要注意。元のビット の最後の要素が続くことになる。 ◦なぜなら、0を足すかぎり、累積和は変わらないので。 つまり、2パータン試す必要がある。 ◦x={0......0??.......?00.....0} または ◦x={0......0??.......?11.....1} 105 w+1個 w個 n個 w+1個 w個 n個 元のビットの部分だけど(番兵ではない) 値が決まっているのに注意。
  106. 106. s 106 x[5],x[6]が0固定の場合 ◦「0にする」を選択する(カットする)→「1にする」が +∞の辺 a0 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 0にする 1にする a3 a2 a1 b0 b1 b2 b3 +∞ +∞ +∞ +∞
  107. 107. s 107 x[5],x[6]が0固定の場合のグラフの最終形 ◦コスト0の辺は省きました。 a0 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] a3 a2 a1 b0 b1 b2 b3 +∞ +∞ +∞ +∞
  108. 108. s 108 a0 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] 0にする 1にする 0にする 1にする 0にする 1にする a3 a2 a1 b0 b1 b2 b3 +∞ +∞ +∞ +∞ x[5],x[6]が1固定の場合 ◦「1にする」を選択する(カットする)→「0にする」が +∞の辺
  109. 109. s 109 a0 x[2] t x[3] x[4] x[5] x[1] x[0] x[6] a3 a2 a1 b0 b1 b2 b3 +∞ +∞ +∞ +∞ x[5],x[6]が1固定の場合のグラフの最終形 ◦コスト0の辺は省きました。
  110. 110. ノードsから辿れる範囲を求める(これ以上流せ ないところcap=0は、リンクがなくなる) ◦ノードsから幅優先探索すればよい。 流し終わったあと ◦sourceからたどれる範囲が、最小カット時のs側。 ◦たどれないほうがt側。その境界がカットするところ。 復元するときは、 ◦x[奇数]・x[偶数]の0,1が互い違いになってること ◦求めるべきなのはkなので、xの差をとることを忘れない。 110
  111. 111. http://ideone.com/7SiimG 111
  112. 112. 112
  113. 113. 113 RabbitWorking 引用: TopCoder - SRM 542 Div1 Hard http://community.topcoder.com/stat?c=problem_statement&pm=11054&rd=14734 N匹(N≦50)のうさぎの集団がいる。 うさぎの集団から何匹かを選ぶ ◦利益の合計Pは、選んだウサギの集団、すべてのペア利 益pikの総和で求められる(0≦pik≦9) ◦費用Cは、C=K(200-K)で求められる。Kは選んだうさぎ の数 効率P/Cを最大化せよ(効率は実数)
  114. 114. 114 兎0 兎1 兎2 兎0 - 7 1 兎1 7 - 2 兎2 1 2 - 兎 0 兎 1 兎 2 兎 0 兎 2 兎 1 P=7+1+2=10, C=3*(200-3)=591, P/C=10/591 P=1, C=2*(200-2)=396, P/C=1/396 うさぎのペア利益pikの表
  115. 115. 「効率P/Cを最大化せよ(効率は実数)」と割 り算がでてきて、どうにもならない。 115 兎 0 兎 1 兎 2 兎 1 兎 0 兎 2 兎 0 兎 2 兎 1 兎 0 兎 2 兎 1 兎 0 兎 2 兎 1 P/C 0 1/396 2/396 10/591 7/396(求めたいのはこれ)
  116. 116. P/C>a/b(a,bは非負整数)を満たすような最大の a/bを求める二分探索にする ◦P/C>x(xは整数)は不可。P/Cは実数をとりうるので。 ◦P/C>x(xは実数)は可能で二分探索はできるが… 最大流の計算時間・精度が不安。 116 兎 0 兎 1 兎 2 兎 1 兎 0 兎 2 兎 0 兎 2 兎 1 兎 0 兎 2 兎 1 兎 0 兎 2 兎 1 P/C Step 2 a/b もっと下 Step 1 a/b もっと上 Step 3 a/b もっと上 Step 4 a/b もっと上 Step 5 a/b もっと下
  117. 117. 割り算を避けるために、二分探索の形にして、両辺 に分母をかけて、整数問題として扱うというテク ニックは、プログラミングコンテストチャレンジ ブック第2版P132「平均最大化」も参考にしてく ださい。 117
  118. 118. 118 푃 퐶 > 푎 푏 푏푃−푎퐶>0 푏 푝푖푗 퐺 푖<푗 −푎퐾200−퐾>0 P/C>a/bを数式変形すると、以上のようになる。 ◦Kは、選んだウサギの数。 ◦Gはウサギの集合。i<jとなるpijの数は、K(K-1)/2。 ◦最小カットに持ち込むなら、このKの値が、辺のコス トに入らないようにしたい。
  119. 119. 119 s ペア 01 t 雇う 組合わせなし 雇う 雇わない 組み合わせあり 雇わない 兎 0 兎 1 グラフは以上のように なりそう(K=1の場合) 1辺のコストにKを使いたくないので (全コスト)=(辺の数)*(1辺のコスト) の形にして、辺の数側にKを組み込んでしまう。 ウサギペアはK(K-1)/2、ウサギの数はK K(K-1)/2 *(???) +K*(???) の形であれば最小カットに持ち込める。
  120. 120. 以上のように数式変形すると ◦ウサギペア K(K-1)/2箇所の辺に、bpij+2aのコスト i<jを満たすのが、 K(K-1)/2個あるので、これでよい。 ◦ウサギ K箇所の辺に 199aのコスト 左辺の最大値>0となればいいので、左辺を最小 カットする。 120 数式はTopCoder公式解説の ものです.
  121. 121. 121 s ペア 01 t 雇う 199a 組合わせなし bp01+2a 雇う 199a 雇わない 0 組み合わせあり 0 兎 0 兎 1 組み合わせあり・なしについては、組み合わせ ありの利益→組み合わせなしの損失に置き換え。 「組み合わせあり」を選んだときは、「雇う」 を選ばせたいので、制約条件の+∞の辺を追加 する。 雇わない 0 +∞ +∞
  122. 122. long long ◦問題では10-9の精度が求められてるので、a/bのa,bを intにすると精度が足りません。辺のコストにlong longの値がくるので、最大流はlong longに対応させ る必要があります。 分数の扱い ◦bを十分に大きい値(1012とか)にして、aを0~1012 で二分探索すれば大丈夫です 別解 ◦P,Cは取れる値の数は実はあまりないので、P/Cの取れ る値も限られます。 この方法だと精度を心配する必要 はなくなります。 ◦http://apps.topcoder.com/wiki/display/tc/SRM+542の公式解説を参考にしてください. 122
  123. 123. http://ideone.com/8QljRJ 123
  124. 124. 124 終わり ここまで読んでくださり ありがとうございました 質問・提案などありましたら Twitterの@nico_shindanninまでお願いします。
  125. 125. Komakiさんのページ ◦http://topcoder.g.hatena.ne.jp/CKomaki/20121019/1350663591 Komiyaさんのページ ◦http://d.hatena.ne.jp/komiyam/20121208/1354895372 プログラミングコンテストチャレンジブック第2版 TopCoder ◦http://community.topcoder.com/tc 125
  126. 126. Dual Core CPU 引用:POJ No.3469 (プログラミングコンテストチャレンジブック P212) http://poj.org/problem?id=3469 N個のモジュールを、コアAかコアBで実行する。 ◦モジュールiをコアAで実行すると、コストがAiかかる ◦モジュールiをコアBで実行すると、コストがBiかかる M個のモジュールの組(ak,bk)はデータ交換を行う ◦もし、akとbkを異なるコアで実行した場合、wkのコスト がさらにかかる。 コストの和の最小値を求めなさい。 1≦N≦20000, 1≦ M ≦200000 126
  127. 127. 127 「何を選択するか」を取り扱うのに、2つ方法が あるので、悩んだ 1.ノードが、s側に属するか、t側に属するかで、選択肢 を割り振る(たいていの他の資料の方法) 3択以上の選択肢、直列に辺がならぶとき(そういう問題 はでてきてないけど)、分かりづらい? 2.辺に、選択肢を割り当て、辺をカットしたら選択した ということにする(本文の方法) 6章の問題のような、カットする選択肢となる辺のコストが 全て0になるときに、説明が不十分かも→でも、いまから全 部直せない…。 min-cutを定式化すると、 푐푖푗푑푖푗(푖,푗)∈퐸の形なので、辺に選 択肢が直結してたほうが、直感的かもと思った。
  128. 128. 128 数式でアプローチする方法 ◦http://en.wikipedia.org/wiki/Max-flow_min- cut_theorem のMin-Cut(Dual)の式は説明したほうが良かっ たかも。 c : 辺のコスト d : カットした辺→1, カットしてない辺→0 p : s側の頂点→1, t側の頂点→0 注 : 上記の定義は、解のうちの1つです。他の値でも最適解をとり うる場合があります。 ◦この式をちゃんと理解しておけば、数学得意な人に対しては、 いらぬ混乱は減らせるかも。 ◦ただ、この式をちょっと変形するなどして、また別なタイプ の問題を解くというのが見えないので、本文中の説明はやめ ておきました。数式を使ったからこそ見えやすい応用があれ ば、本文中に入れたのですが。 ◦あと、Komiyaさんのページのほうがずっと良いので、自分が 説明しないほうが良い気もしました(泣)

×