B - 饂飩屋の席 / Seats in an Udon Restaurant Editorial by admin
gpt-6-astra-medium概要
空席が最も多い行を求めます。同じ数の空席を持つ行が複数ある場合は、最も上の行を選びます。
考察
どの行にも座席は \(W\) 個あるため、各行について次の関係が成り立ちます。
\(空席数 = W - 人が座っている座席数\)
したがって、空席が最も多い行は、人が座っている座席が最も少ない行です。提示されたコードでは、各行の o の個数を数え、その個数が最小の行を探しています。
例えば、座席表が次の場合を考えます。
o.o.
....
.o..
....
各行の o の個数は順に \(2, 0, 1, 0\) 個です。最小なのは \(2\) 行目と \(4\) 行目なので、最も上にある \(2\) 行目が答えです。
すべての座席を調べても最大で \(10 \times 10 = 100\) 席なので、素朴に全探索しても十分高速です。
注意すべきなのは、同数の場合の扱いです。上から順に調べるとき、最小値と同じ場合にも答えを更新すると、より下の行を選んでしまい、誤答になります。これまでの最小値より小さい場合だけ更新することで、最も上の行を残せます。
アルゴリズム
- これまでに見つかった着席数の最小値
bestSeatedを、十分大きな値で初期化します。答えの行番号をidxに記録します。 - 上から順に、行番号 \(i = 1, 2, \ldots, H\) について次を行います。
- その行の文字列を読み込みます。
- 文字列中の
oの個数を数え、seatedとします。 seated < bestSeatedの場合だけ、bestSeatedをseatedに、idxを \(i\) に更新します。
idxを出力します。
この処理では、各行を調べ終えた時点で、idx は「そこまでの行のうち、着席数が最小で、最も上にある行」を表します。そのため、すべての行を調べ終えた後の idx が求める答えです。
計算量
- 時間計算量: \(O(HW)\)
各行の \(W\) 文字を、\(H\) 行分調べます。 - 空間計算量: \(O(W)\)
一度に保持するのは長さ \(W\) の文字列と、定数個の変数だけです。
実装のポイント
bestSeatedの初期値は、着席数の最大値 \(W\) より大きくします。コードでは1 << 30を使っており、最初の行で必ず更新されます。更新条件は
seated < bestSeatedとします。<=にすると、同数の場合に下の行で上書きされてしまいます。出力する行番号は \(1\) 始まりなので、コードでは行を調べるループも \(1\) から始めています。
空席がまったくない場合でも、すべての行の着席数が同じになるため、正しく \(1\) 行目が選ばれます。
ソースコード
// 問題文から独立に実装: 着席数が最も少ない行(同数なら最初)を探す
#include <iostream>
#include <string>
int main() {
int h, w; std::cin >> h >> w;
int bestSeated = 1 << 30, idx = 0;
for (int i = 1; i <= h; ++i) {
std::string s; std::cin >> s;
int seated = 0;
for (int j = 0; j < w; ++j) if (s[j] == 'o') seated++;
if (seated < bestSeated) { bestSeated = seated; idx = i; }
}
std::cout << idx << std::endl;
}
この解説は gpt-6-astra-medium によって生成されました。