More Related Content Similar to 最小カットを使って「燃やす埋める問題」を解く
Similar to 最小カットを使って「燃やす埋める問題」を解く (6) 最小カットを使って「燃やす埋める問題」を解く2. 1. 燃やす埋める問題とは
2. 基本
3. 選択肢をうまく並べる
4. 二部グラフの性質を生かす
5. 複雑な制約条件を入れる
6. 最小カットの復元をする
7. 費用を工夫して割り当てる
2 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 11. 11
燃やす埋める問題 Super Easy
A,B,Cは「燃やす」か「土に埋める」必要がある。
◦A,B,Cは「燃やす」とそれぞれ50,60,130円かかる。
◦A,B,Cは「土に埋める」と100円かかる。
最小で何円かかるか? 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
s
A
B
t
C
50
60
130
100
100
100
燃やす
燃やす
燃やす
土に埋める
土に埋める
土に埋める
頂点sから頂点tへ辺をつなげる。
◦小問題ごとに並列につなげる
◦選択肢は直列につなげる 14. 14
s
A
B
t
C
50
60
130
100
100
100
燃やす
燃やす
燃やす
土に埋める
土に埋める
土に埋める
最小s-tカットは、このようになる。
◦最小で50+60+100=210でs→tがつながらなくなる。
◦カット(赤い線)した部分が、小問題の選択肢になる。 15. 15
s
A
B
t
C
50
60
130
100
100
100
燃やす
燃やす
燃やす
土に埋める
土に埋める
土に埋める
最小s-tカットは、このようになる。
◦最小で50+60+100=210でs→tがつながらなくなる。
◦カットした部分が、小問題の選択肢になる。 19. 19
燃やす埋める問題 Very Easy
A,B,Cは「燃やす」か「土に埋める」必要がある。
◦A,B,Cは「燃やす」とそれぞれ50,60,130円もらえる。
◦A,B,Cは「土に埋める」と100円もらえる。
最大で何円もらえるか? 20. 20
燃やす埋める問題 Very Easy
A,B,Cは「燃やす」か「土に埋める」必要がある。
◦A,B,Cは「燃やす」とそれぞれ50,60,130円もらえる。
◦A,B,Cは「土に埋める」と100円もらえる。
最大で何円もらえるか?
最小カットは、最小値を求める。最大値ではない。
そこで、最小値を求める問題に置き換える! 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
燃やす
土に埋める
A
50円の利益
100円の利益
B
60円の利益
100円の利益
C
130円の利益
100円の利益
これはダメ!
◦負辺があるときの最小カット問題はNP困難
燃やす
土に埋める
A
-50円の損失
-100円の損失
B
-60円の損失
-100円の損失
C
-130円の損失
-100円の損失 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. s
A
B
t
C
50
40
0
0
0
30
燃やす
燃やす
燃やす
土に埋める
土に埋める
土に埋める
コスト0の辺もグラフに書きましょう!
◦最小カット問題のグラフでは、 辺が元からないのと、損失0の辺とでは、別物です。
◦最大フローを求めるときに、容量0になるのでいらない辺に なりますが、それでも書きましょう
◦複雑な問題だと、辺が元からないのか、辺があるけどコスト が0なのかで、混乱しやすくなる。 26. 26
燃やす埋める問題 Easy
A,Bは「燃やす」か「土に埋める」必要がある。
◦A,Bは「燃やす」とそれぞれ20,100円かかる。
◦A,Bは「土に埋める」とそれぞれ50,20円かかる。
◦Aを燃やしたときに、Bを土に埋めると罰金300円かかる。
最小で何円かかるか? 27. 27
s
A
B
t
20
100
50
20
燃やす
燃やす
土に埋める
土に埋める
Aを燃やしたときにBを土に埋めると 罰金300円かかる 28. 28
s
A
B
t
20
100
50
20
燃やす
燃やす
土に埋める
土に埋める
Aを燃やしたときにBを土に埋めると 罰金300円かかる
Aを燃やしたときにBを土に埋めたら まだs-tカットが成立しないようにする 29. 29
s
A
B
t
20
100
50
20
燃やす
燃やす
土に埋める
土に埋める
Aを燃やしたときにBを土に埋めると 罰金300円かかる
Aを燃やしたときにBを土に埋めたら まだs-tカットが成立しないようにする
300
罰金 30. 30
s
A
B
t
20
100
50
20
燃やす
燃やす
土に埋める
土に埋める
こうすると、s-tカットするにはB→Aの辺をカッ トせざるをえない。つまり300円かかる。
もちろん、これは最小カットではない。
この制約条件の追加方法を理解できないと その後すべて理解できなくなるので注意!
300
罰金 31. 31
s
A
B
t
20
100
50
20
燃やす
燃やす
土に埋める
土に埋める
両方を土に埋めると最小カット70円になります。
300
罰金 35. 35
s
A
B
t
C
50
60
130
100
100
100
燃やす
燃やす
燃やす
土に埋める
土に埋める
土に埋める
選択肢はどういう順番に置いてもよい。
◦ただ、順番が悪いと、制約条件を追加できないことが ある。
考えて選択肢の順番を決めないといけない。 36. 36
FoxAndGo3
引用:TopCoder - SRM594 Div1 Medium
http://community.topcoder.com/stat?c=problem_statement&pm=12808&rd=15706
囲碁っぽい問題。自分が黒番で好きなだけ黒石を 置ける。(死ぬ場所にも置けるので注意)
黒石で白石のまわりを隙間なく囲めば白石を除い て領地(=空きマス)にすることができる。
領地の最大値を求めよ。
盤面の数は最大で50*50。また、白石同士は隣接 していない。 42. 42
最大値を求める問題なので、このままでは 最小カットが使えない。
◦黒石が最初からおいてあるところは絶対領地にできない
◦つまり、仮の最大領地数=盤面の全マスー黒石数
◦そこから逆に以下のように考える
白石がとれなかったら、領地1の損失
領地(空きマス)で黒石をおいたら、領地1の損失
◦仮の最大領地数ー最小の領地損失=最大の領地数で求め ることができる。 43. 43
s
t
1
0
1
0
1
0
黒置く
白死領地
黒置く
領地
白のまま
黒石は無視してよい。選択肢がないから。
領地を1の損失と考えたこのグラフは正しい。
「白死領地にするには、まわりに黒を置かない といけない」の制約をどうするか?
領地
白石と隣接する領地 (空きマス)
白石 44. s
t
1
0
1
0
1
0
黒置く
白死領地
黒置く
領地
白のまま
領地
この2つを強制的に切らせたい 45. s
t
1
0
1
0
1
0
黒置く
白死領地
黒置く
領地
白のまま
領地
+∞
+∞ 46. s
t
1
0
1
0
1
0
黒置く
白死領地
黒置く
領地
白のまま
領地
+∞
+∞
+∞の制約条件を入れても、最小カットが成立 してしまう。「黒置く」のところを強制的に カットさせたいのにできない。
+∞のリンクを逆にしても、同じ。 47. 47
s
t
0
0
0
1
1
1
領地
白死領地
領地
黒置く
白のまま
「黒置く」と「領地」の選択肢の順番を変える
黒置く 48. 48
s
t
0
0
0
1
1
1
領地
白死領地
領地
黒置く
白のまま
+∞の辺を白から領地の方向へ足す
黒置く
+∞
+∞ 49. 49
s
t
0
0
0
1
1
1
領地
白死領地
領地
黒置く
白のまま
黒置く
+∞
+∞
こうすると、領地の辺をカットしても、 まだs-tは繋がっている。最小s-tカットになってい ないので、解にならない。
◦つまり、元からの領地の部分に黒石をおかないのであれば、 白石を殺して領地にすることはできないという意味。 50. 50
s
t
0
0
0
1
1
1
領地
白死領地
領地
黒置く
白のまま
黒置く
+∞
+∞
仮に隣接する1カ所をカットしても まだs-tは繋がっている 51. 51
s
t
0
0
0
1
1
1
領地
白死領地
領地
黒置く
白のまま
黒置く
+∞
+∞
つまり、隣接する領地は、すべて「黒置く」を選ば ないと、s-tカットできない。
「白石を殺して領地にするには、まわりに黒を置か ないといけない」という制約通りになってる。 52. 52
s
t
0
0
0
1
1
1
領地
白死領地
領地
黒置く
白のまま
黒置く
+∞
+∞
うっかり+∞の辺を領地から隣接する白方向に 足すと、うまくいかない。
上の例で、「黒置く」をカットしなくても、s-t カットができている。 53. 53
s
t
0
0
0
1
1
1
領地
白死領地
領地
黒置く
白のまま
黒置く
+∞
+∞
うっかり+∞の辺を領地から隣接する白方向に 足すと、うまくいかない。
上の例で、「黒置く」をカットしなくても、s-t カットができている。 54. 54
FoxAndGo3
引用:TopCoder SRM594 Div1 Medium
http://community.topcoder.com/stat?c=problem_statement&pm=12808&rd=15706
囲碁っぽい問題。自分が黒番で好きなだけ黒石を 置ける。(死ぬ場所にも置けるので注意)
黒石で白石のまわりを隙間なく囲めば白石を除い て領地(=空きマス)にすることができる。
領地の最大値を求めよ。
盤面の数は最大で50*50。また、白石同士は隣接 していない。←この条件があると、囲む判定を工 夫する必要がありますが、それでも解けます。 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 67. 67
s
t
4
4
白にする
青にする
?
?
白にする
0
EVEN
ODD
0
青にする
2
+∞
2
ODD
EVEN
2
+∞
◦ODD側の青マスからt側に+∞の辺を足す。
これでグラフが完成です。 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
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
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
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
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 82. 82
s
置 く
t
置く
置かない
bi-ci
0
囲 む
囲まれない
bi
囲まれる
0
+∞
EVEN (偶数マス)
ODD
(奇数マス)
置 く
置く
置かない
bi-ci
0
囲 む
囲まれない
bi
囲まれる
0
+∞
「囲まれるには、周り全てに置く必要がある」 の制約条件を入れる準備として、奇数ODDマスの選択 肢をすべて逆にする。 83. 83
s
置 く
t
置く
置かない
bi-ci
0
囲 む
囲まれない
bi
囲まれる
0
+∞
置 く
置く
置かない
bi-ci
0
囲 む
囲まれない
bi
囲まれる
0
+∞
EVEN (偶数マス)
ODD (奇数マス)
「囲まれる」とき「隣に置かない」のは禁止なので これらを選んだ時にs-tカットができないように+∞ の辺を貼ればよい。
+∞
+∞ 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点得られる.
スコアを最も多く得られるようなビット列を求め よ. 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] 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
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. 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
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. 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. 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にする
+∞
+∞ 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
+∞
+∞
+∞
+∞ 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. 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の辺は省きました。
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
兎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の表 118. 118
푃 퐶 > 푎 푏
푏푃−푎퐶>0 푏 푝푖푗 퐺 푖<푗 −푎퐾200−퐾>0
P/C>a/bを数式変形すると、以上のようになる。
◦Kは、選んだウサギの数。
◦Gはウサギの集合。i<jとなるpijの数は、K(K-1)/2。
◦最小カットに持ち込むなら、このKの値が、辺のコス トに入らないようにしたい。 119. 119
s
ペア 01
t
雇う
組合わせなし
雇う
雇わない
組み合わせあり
雇わない
兎 0
兎 1
グラフは以上のように なりそう(K=1の場合)
1辺のコストにKを使いたくないので (全コスト)=(辺の数)*(1辺のコスト) の形にして、辺の数側にKを組み込んでしまう。
ウサギペアはK(K-1)/2、ウサギの数はK
K(K-1)/2 *(???) +K*(???) の形であれば最小カットに持ち込める。 121. 121
s
ペア 01
t
雇う
199a
組合わせなし
bp01+2a
雇う 199a
雇わない 0
組み合わせあり
0
兎 0
兎 1
組み合わせあり・なしについては、組み合わせ ありの利益→組み合わせなしの損失に置き換え。
「組み合わせあり」を選んだときは、「雇う」 を選ばせたいので、制約条件の+∞の辺を追加 する。
雇わない
0
+∞
+∞ 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 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
「何を選択するか」を取り扱うのに、2つ方法が あるので、悩んだ
1.ノードが、s側に属するか、t側に属するかで、選択肢 を割り振る(たいていの他の資料の方法)
3択以上の選択肢、直列に辺がならぶとき(そういう問題 はでてきてないけど)、分かりづらい?
2.辺に、選択肢を割り当て、辺をカットしたら選択した ということにする(本文の方法)
6章の問題のような、カットする選択肢となる辺のコストが 全て0になるときに、説明が不十分かも→でも、いまから全 部直せない…。
min-cutを定式化すると、 푐푖푗푑푖푗(푖,푗)∈퐸の形なので、辺に選 択肢が直結してたほうが、直感的かもと思った。 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さんのページのほうがずっと良いので、自分が 説明しないほうが良い気もしました(泣)