Open tipstar0125 opened 1 year ago
出現確率分布の活用に関して
ビームサーチ
コンテスト中の解法 ・S or L or Rの中で最適な動作を評価関数で判定 ・レベルアップを最優先として、次に残り体力が少なく倒せそうな敵ならスコアを高くした ・死んだときのスコアは-INF ・スコア同じ場合は留まることにした ・周りに敵がいない場合は左右どちらかに確率で移動
得点:2,859,502 サンプル得点:約36,000
まずは貪欲法をやってみたい。
なるべく多くの敵機を破壊する貪欲法 一番早く破壊できる敵機だけを狙えば良い動きができそう 自機を動かす際、次のターンに敵機に衝突してしまったり、敵機に包囲されて回避不能になってしまわないように注意
貪欲法
注意点!!!:自機と敵の距離が1になって、敵を消滅できなければ、次のターンで確定Game over
貪欲法の提出
コンテストでも貪欲書いたけど、Game overのタイミングを勘違いしてた。。。 「自機と敵の距離が1になって、敵を消滅できなければ、次のターンで確定Game over」
check_left/right_enemyの判定dy < t
をdy <= t
に修正:3,810,330点
https://yukicoder.me/submissions/895616
judge_collision_left/rightを改善:3,891,630点 次のターンで目の前に敵がくる場合も衝突判定していたが、実際は倒せれば問題ないので、倒せる場合は衝突しないとした。 https://yukicoder.me/submissions/895624
左右どちらにも倒せる敵がいない場合、強制で左に移動:3,763,608点 https://yukicoder.me/submissions/895616
左右どちらにも倒せる敵がいない場合、左右ランダム:3,279,230点 https://yukicoder.me/submissions/895367
ランダムで左右に動くと、敵がいないところを反復横跳びして、終盤敵を倒せないので、強制的にどちらかに流れてしまった方が点数取りやすいのかもしれない。
もう少し貪欲を頑張りたい。 改善点としては、正面・左右どこにも倒せる敵がいなかった場合、どう動くのか最適かを適切に求めたい。
ただし、2手先以上は衝突を回避しつつ、どこで留まるべきかを決めるのは貪欲では厳しそう。 衝突回避は難しいので、 一旦敵がいるところまで探索して、左右どちらが有利か決める方針を書いてみるのはよさそうな気がする。
左右どっちに行った方が良いのか、敵の密度を求めると良さそうな気もするので、それでやってみる。
pokaさんも貪欲だったから、後でみておきたい!
一旦敵がいるところまで探索して、左右どちらが有利か決める方針を書いてみるのはよさそうな気がする。
3,777,131点 https://yukicoder.me/submissions/895625
隣より先を探索しても、すぐ倒せなければ、あまり意味ないかも(新しい敵が出現したりするので) あと、ビジュ見ると比較的弾幕なので、敵が過疎っている状況(序盤)をがんばっても意味がなさそう。
今気づいたんだが、levelはpowerで上がっていくけど、scoreはhpであがっていく。。。 scoreとlevel同じだと思ってた。 最初はレベルアップ重視で、後半はスコア重視にすると良さそう。
書いてみた:3,755,820点 https://yukicoder.me/submissions/895760
seed0002でうまくいっていないっぽい。 目の前、左に敵がいなくて、右に倒せる敵がいない場合は留まっている。 敵がいないとき、倒せないときの優先順位とタプルのソートの影響。少し工夫がいる。
評価値計算で、hp or pが小さく、tが大きい場合は0になってしまい、正しく評価できないので1e6をかけて評価したら、ちょっとだけスコア上がった。 3,869,015点 https://yukicoder.me/submissions/896736
貪欲色々改善したけど、超絶激固弾幕??があるっぽくて、ローカルテストケース100ケで問題なくても、提出したら点数が伸びない。どこかでGame overになっている。 貪欲は3.8-3.9Mで限界説。
試した改善
pokaさんコメント: LRSの3択ではなく、どの列の敵を狙うかの貪欲を使ってですが一応4.29Mまででましたよ。 評価値は(敵機のinit_hpとpowerの重み付き和) / (敵機を破壊するまでにかかるターン) に加えて各列周辺の敵の密度的なものを使っています
コード(Rust) https://yukicoder.me/submissions/896568
pokaさんのコメントを受けてどの列を狙うかの貪欲を書いてみた。 ただ、全ての列に最短で到達できるターン数を求めるとTLEするので、最大8ターンで到達できる範囲で計算した。 ※途中移動中に敵を倒すこともあるが、評価値には考慮していない
4,137,041点 https://yukicoder.me/submissions/896738
各列に対して最短で到達できるターン数をBFSでもとめたけど、行まで拡大してBFSすると、重複キューがなくなり、高速になる?? ⇒関数名bfs2。若干?早くなったけど、あまり高速化できなくて、点数も変化なし:4,116,568点 https://yukicoder.me/submissions/896912
各列の先頭の敵のみで評価値を計算していたのを、全ての敵に変更した。あまりのびず。:4,056,776点 https://yukicoder.me/submissions/896990
各列の先頭の敵のみで評価値を計算していたのを、全ての敵に変更したv2。bf2(8turn)使用:4,277,879点 https://yukicoder.me/submissions/896992 ※スコアが伸びなかった方は、敵を倒すたびにscore/turnを積算していたが、scoreとturnを積算して、最後にscore/turnを評価値とする
移動の途中でダメージ与えるのは無視しても、倒せる敵は考慮しやすそうだから、評価値に加えた方がよさげ?? ⇒ビームサーチした方が実装しやすそう。。。
ターンが進むごとに、評価値はスコアの取得を重視、powerの取得の影響をさげていくこともやってみたが、効果が出なかった。。。なぜだろう。。。 ⇒現時点のhpではなく、init_hpで評価しないと、powerの評価と同じにならない ので、評価に使用するパラメータをhpからinit_hpに変更:4,296,090点 https://yukicoder.me/submissions/897111
pokaさんコード(4.29M点)解読 https://yukicoder.me/submissions/896568
貪欲をさらにがんばろうとすると結局ビームサーチっぽいことになる(すでにビームサーチっぽいけど)。 ビームサーチをやった方がよさそうなので、ここら辺で貪欲を切り上げる。
貪欲まとめ:
重要
:評価関数は最終的には問題のスコアに近づくようにした方がよい。やり方には2通りあって、ある閾値(今回の場合レベル)を境に評価関数を変えるとか、レベルごとに重みを変化させる。2つのやり方を混ぜるのもあり。
最大4,296,090点獲得 https://yukicoder.me/submissions/897111
ビーム打ってみた。 ビームの深さが5までしかいかないので、5ターンでスコアを獲得できない場合は、全てのスコアが同じになって、その場にとどまってしまい、最後まで残ったとしてもスコアが全く伸びない。 https://yukicoder.me/submissions/897194
改善案
bowwowさんツイート:
敵を1体倒すまでを深さ1としたビームサーチ。深さ4の幅8までしかできなかった。 https://twitter.com/bowwowforeach/status/1680521601559691265
コピー量を減らす案:
問題:https://yukicoder.me/problems/no/5017 解説:https://yukicoder.me/problems/no/5017/editorial
ぷらちなさんWriter記:https://platinum-prog.hatenablog.com/entry/2023/07/25/181223 rhooさん解法(ビムサ):https://twitter.com/rho__o/status/1681665412843421699 pokaさん解法(貪欲):https://twitter.com/poka_cp/status/1680559487369838596