コンテストページ: パナソニックグループプログラミングコンテスト2023(AtCoder Beginner Contest 301) - AtCoder
コンテスト中AC: A〜C
コンテスト後にD,Eを自力AC
D - Bitmask
以下の説明で、の最大値を十分に超えるため、最上位ビットを63としておきます。
がこれより小さい場合はサイズが63になるように0を追加しておきます。
上位のビットから?のビットを決定していくことを考えます。上位ビットをできるだけ大きくした方が、値として大きくできるため、優先します。
この時、より小さい数にするために、?を使うのは高々1箇所であると言えます。なぜなら、一度
未満となれば、その後の下位ビットをどのようにしたとしても、
以上となることはありえないからです。
仮に番目のビットで
が
未満であることが確定した場合に最適解であったとします。この時、最上位ビットから
番目までのビットは
と
で一致していることが言えます。
もし一致していなければ、番目より上位のビットで
が
未満であるか、
より大きいかのいずれかとなってしまいます。
また、番目以降の?は全て1にするのが最適です。
を
未満にするというのは、
の
ビット目が1であり、かつ、
の
ビット目が?である状況で、?を0にすることと言えます。
そこで、の?を1つずつ0にした場合について、その時の
の最大値を全探索します。この時、
の最上位ビットから
ビット目までについて、?の箇所を全て
と同一にし、
以降は0であるような値
の0ビット目から
ビット目までについて、?の箇所を全て1とし、
ビット目以降は0であるような値
となるように配列を作っておくと、
ビット目で
未満となった時の値を
で計算できます。但し、便宜上、
とします。(ビットを1オリジンで実装すれば-1が0になって実装しやすくなります。)
解の最大値の更新は、この値が以下である場合のみ行えばよいです。
テーブルはで構築でき、全探索も
でできます。
なお、未満となる箇所が0箇所の場合も考慮する必要があります。これは、
と同じです。
実装: Submission #41405709 - Panasonic Programming Contest 2023(AtCoder Beginner Contest 301)
E - Pac-Takahashi
同じお菓子を2回食べられないので、既に食べたお菓子の状態を冪集合で管理したいです。状態数分のマスを拡張したBFSはおそらく計算量的に厳しいです。
考慮すべきは、スタート-お菓子、お菓子-お菓子、お菓子-ゴール間の最短距離のみです。また、後は各状態に対する移動距離の最小値が求められればよいです。ここで思いつくのが巡回セールスマン問題です。
お菓子を頂点とみなします。また、計算量は定数倍落ちますが、実装の簡便さからスタートとゴールも頂点とみなします。
これら頂点に対する巡回セールスマン問題を考えると、状態で頂点
にいる場合の最短距離を、頂点数を
として
で求めることができます。
最短距離を求めた後は、ゴールの頂点にいるdp値について、以下か調べます。
以下であれば、冪集合の1の数をカウントし、更にそこからスタートとゴールの頂点数2を引いた値で、答えの最大値を更新すればよいです。
全点対間最短経路は各頂点からBFSすることで、で求められます。
実装: Submission #41471658 - Panasonic Programming Contest 2023(AtCoder Beginner Contest 301)
なお、詳細は割愛しますが、スタートとゴールは巡回セールスマン問題を解く時の頂点から除いて考えることができ、定数倍軽くなります。但し、例外処理などに気をつける必要があります。
実装: Submission #41471658 - Panasonic Programming Contest 2023(AtCoder Beginner Contest 301)