Upload
yowaken
View
316
Download
3
Embed Size (px)
Citation preview
TopCoder Marathon Match 92Lighting
参加メモ
@yowa
どんな問題?
● 壁のある部屋にライトを置いて、できるだけ部屋全体を照らしたい
– 部屋サイズS: 10~50
– ライトの数L: 2~10
– ライト半径D: 2~10
– 壁である確率p: 0.1~0.3
● スコア: 照らしてる割合
やったこと
● 大ざっぱなライトの配置を決める– ライト位置を各セルの中心・角・辺中央に限定
– 照らす範囲もすごい雑に計算
– Greedy に配置した後、焼きなまし● 焼きなましの近傍: ライトを1つ任意の位置に移動する
● 位置を微調整する– 照らす範囲の計算をもうちょい細かく
– 焼きなまし● 近傍: ライトを現位置から±1セル分以内で動かす
今回の問題のキモ(?)
● スコア計算をどう実装するか?
– 複数ライトが照らしている面積の和(union)を求める
スコア計算の詳細(定義)
● 各セルをf^2個のサブセルに分割(分割数 f=100)● サブセルの中央にライトの光が届いていれば、そ
のサブセル全体が照らされているとみなす
● 光が届く⇔ライトとの距離がD以内、かつ
ライトへの線分が、壁と交わらない
(壁に接するのもアウト)
スコア計算の(公式テスタの)実装
● すべてのサブセル(= f^2・S^2)について
● すべてのライト(= L)からの線分が
● すべての壁(= p・S^2) と交差しないか確かめる
● → f^2・p・L・S^4 回の交差判定
スコア計算の(公式テスタの)実装
● すべてのサブセル(= f^2・S^2)について
● すべてのライト(= L)からの線分が
● すべての壁(= p・S^2) と交差しないか確かめる
● → f^2・p・L・S^4 回の交差判定
重い
スコア計算の実装
● 公式テスタ→ひどいケースは1回で十数秒かかる
● 焼きなましなどをやりたい
→ スコア計算は何万回と行う必要がある
● 効率化・簡略化による高速化が不可避
スコア計算でやったこと
● 部屋を(サブセルではなく)縦に細くスライスする
スコア計算でやったこと
● 部屋を(サブセルではなく)縦に細くスライスする● 一つのライトが照らす範囲 ≒
– 各スライスについて
– 各壁がつくる影の区間を[y_min, y_max]で求め
– すべての壁について union をとって、
– 反転(陰→陽)したもの
スコア計算でやったこと
● 部屋を(サブセルではなく)縦に細くスライスする● 一つのライトが照らす範囲 ≒
– 各スライスについて
– 各壁がつくる影の区間を[y_min, y_max]で求め
– すべての壁について union をとって、
– 反転(陰→陽)したもの
● 複数のライトが照らす範囲 ≒
– スライスごとに、各ライトが照らす範囲を union
計算量?
● サブセルの縦方向の分割が減ったけど
– 区間の union が O(1) じゃないぶん増えた
– ここは相殺する感じ
● おおまかに、元の計算量の f^2 が、
スライス分割数 f になる、くらいの改善?
計算量 ?
● 前ページの計算量– ライトが照らす範囲を毎回計算する前提
● 一度計算したライト位置についてはメモしておく● 全部メモ済ならば、
– すべてのライト(= L)について
– すべてのスライス(= f・S)における
– 照らす範囲(高々S+2個の区間)を union する
● ので、2f・L・S^2 とかかなあ?
精度を犠牲に高速化
● セルごとの分割数 f = 100 を減らす
● 最初のGreedy&焼きなましでは f = 2 で● 次の微調整ターンでは f = 10 で
やらなかったこと
● 厳密なスコアの計算
– f = 100 じゃないと正確じゃないけど仕方ないね
– いまになって出力を眺めたら、円の角が欠けてる例が散見されて悲しみを覚えた
こっちに置けるのに…
やらなかったこと
● 厳密なスコアの計算
– f = 100 じゃないと正確じゃないけど仕方ないね
– いまになって出力を眺めたら、円の角が欠けてる例が散見されて悲しみを覚えた
● 小さいケースで厳密解
– Dが小、 L が少など:円が互いに交わらない解が存在
– Dが小 → 範囲内の壁状況のパターンも限定的
– 全パターンの網羅が可能のはず
まとめ
Splatoon っぽい……Splatoon っぽくない?