待ち行列シミュレーター
レジや窓口の行列を、到着・開始・終了・待ち時間の4つの数字で表すシミュレーションです。 「開始時刻 = 最大値(到着時刻, 前の人の終了時刻)」の式で待ちが決まる様子を確認できます。
動きを1ステップずつ確認する
人数
混み具合
時間の流れ(分)
- 待ち時間
- 対応中
求めた時刻(分)
| 客 | 到着 | 開始 | 終了 | 待ち |
|---|
ここまでの最大待ち時間
–
まだ決まっていません
i
–
到着
–
開始
–
終了
–
待ち
–
パソコンではキーボードでも操作できます:→ 次へ / ← 前へ / スペース 再生・一時停止
実行ログを見る(ここまでの処理)
ALGORITHM
待ち行列シミュレーションとは何をしているか
レジや窓口に人が並ぶ様子を、4つの数字の列で表して1人ずつ計算していくシミュレーションです。
- 到着時刻 Arrive[i] … その人が列に並んだ時刻(問題文で与えられる)
- 開始時刻 Start[i] … 対応してもらい始めた時刻(求めるもの)
- 終了時刻 Finish[i] … 対応が終わった時刻(求めるもの)
- 待ち時間 … Start[i] - Arrive[i](求めるもの)
中心にあるのは「最大値」の式
このアルゴリズムで覚えることは、実質この1行だけです。
Start[i] = 最大値(Arrive[i], Finish[i - 1])
対応を始めるには2つの条件がそろう必要があります。 ひとつは「自分が到着していること」、もうひとつは「前の人が終わっていること」です。 2つがそろう時刻は、2つのうち遅いほう、つまり最大値になります。
| 状況 | どちらが遅いか | 結果 |
|---|---|---|
| 到着したとき、窓口が空いていた | 到着時刻のほうが遅い | すぐ開始(待ち 0 分) |
| 到着したとき、まだ前の人が対応中 | 前の人の終了時刻のほうが遅い | 前の人が終わるまで待つ |
最初の人だけ別に計算する
最初の人には「前の人」がいません。Finish[-1] は存在しないので比べる相手がなく、
到着した時刻にそのまま開始できます。そのため Start[0] = Arrive[0] と先に書き、
繰り返しは i = 1 から始めます。これは配列を扱うアルゴリズム全般でよくある形です。
待ちが積み上がる条件
シミュレーターで混み具合を切り替えると、待ち時間の出方がはっきり変わります。
- すいてる(到着間隔 > 対応時間)… 誰も待ちません。窓口が空く時間があります。
- 混んでる(到着間隔 < 対応時間)… 待ち時間が後ろの人ほど長くなります。行列が伸び続けます。
- 同時到着(全員が0分に到着)… 2人目以降は前の人の終了をそのまま待ちます。待ち時間は対応時間の倍数になります。
ポイント:「到着の間隔」と「1人あたりの対応時間」のどちらが長いかで、行列が伸びるか解消するかが決まります。
対応時間を変えると同じ到着でも結果が変わるので、シミュレーターの「対応時間」を切り替えて確認してください。
CODE
3つの書き方で見る待ち行列
Arrive = [0, 3, 6, 7] service = 4 Start = [0, 0, 0, 0] Finish = [0, 0, 0, 0] Start[0] = Arrive[0] Finish[0] = Start[0] + service i を 1 から 要素数(Arrive) - 1 まで 1 ずつ増やしながら繰り返す: |Start[i] = 最大値(Arrive[i], Finish[i - 1]) ⎿ Finish[i] = Start[i] + service 表示する(Start, Finish)
arrive = [0, 3, 6, 7]
service = 4
start = [0] * len(arrive)
finish = [0] * len(arrive)
start[0] = arrive[0]
finish[0] = start[0] + service
for i in range(1, len(arrive)):
start[i] = max(arrive[i], finish[i - 1])
finish[i] = start[i] + service
print(start, finish)
const arrive = [0, 3, 6, 7];
const service = 4;
const start = new Array(arrive.length).fill(0);
const finish = new Array(arrive.length).fill(0);
start[0] = arrive[0];
finish[0] = start[0] + service;
for (let i = 1; i < arrive.length; i++) {
start[i] = Math.max(arrive[i], finish[i - 1]);
finish[i] = start[i] + service;
}
console.log(start, finish);
最大値の書き方:擬似言語の
最大値(a, b) は、Python では max(a, b)、
JavaScript では Math.max(a, b) です。
もし a > b ならば … そうでなければ … と条件分岐で書いても同じ結果になります。
穴埋めで「最大値」が空欄になったら、条件分岐に置き換えられるかも確認しておきましょう。
EXAM POINT
共通テスト「情報Ⅰ」での出題ポイント
- 最大値の式:
Start[i] = 最大値(Arrive[i], Finish[i - 1])の空欄。なぜ最大値なのかを説明できることが要点です。 - 表の穴埋め:到着時刻だけが与えられ、開始・終了・待ち時間の表を完成させる形。上から順に1行ずつ埋めていきます。
- 待ち時間の式:
待ち時間 = Start[i] - Arrive[i]。引く順番を逆にしないよう注意します。 - 繰り返しの開始値:
i = 1から始まる理由。最初の人には前の人がいないためです。 - 条件を変えたときの変化:「対応時間を短くすると待ち時間はどうなるか」「窓口を2つにしたら」といった応用。
表を埋めるコツ:1行ずつ「到着 → 前の人の終了と比べる → 遅いほうが開始 → 開始 + 対応時間が終了」の順に埋めます。
シミュレーターの「表」タブは、まさにこの手順で1マスずつ埋まっていきます。
自分で表を書いてから、答え合わせに使ってください。
MISTAKES
よくある間違い
| 間違い | 何が起きるか | 正しくは |
|---|---|---|
| 最小値で計算する | 前の人が終わる前に開始してしまう | 最大値(遅いほう)を使う |
| 開始時刻をいつも到着時刻にする | 待ち時間が常に0になる | 前の人の終了と比べる |
| 前の人の「開始」と比べる | 対応時間ぶんだけ早く始まってしまう | 前の人の「終了」Finish[i - 1] と比べる |
| 繰り返しを i = 0 から始める | Finish[-1] という存在しない要素を参照する | 最初の人は別に計算し、i = 1 から回す |
| 待ち時間を到着 - 開始で計算する | 符号が逆になり負の数になる | 開始 - 到着 |
CHECK
理解度チェック
Q1. Arrive = [0, 3, 6, 7]、対応時間4分のとき、Start はどうなりますか。
Start = [0, 4, 8, 12]。
1人目は 0 に開始し 4 に終了。2人目は到着 3 より終了 4 が遅いので 4 に開始(待ち1分)。
3人目は到着 6 より終了 8 が遅いので 8 に開始(待ち2分)。4人目は 12 に開始(待ち5分)です。
後ろの人ほど待ち時間が長くなっています。
Q2. 同じ到着時刻で、対応時間を2分に短くすると待ち時間はどうなりますか。
すべて0分になります。
Start = [0, 3, 6, 7] となり、全員が到着と同時に開始できます。
到着の間隔が対応時間より長ければ、待ちは発生しません。
シミュレーターで対応時間を2分に変えて確認してください。
Q3. 4人が全員0分に到着し、対応時間が4分のとき、4人目の待ち時間は何分ですか。
12分。
開始時刻は 0, 4, 8, 12 となり、4人目は到着 0 に対して開始が 12 なので待ちは 12 分です。
全員同時に到着した場合、待ち時間は対応時間の倍数で増えていきます。
Q4. 「最大値」を使わずに同じ処理を書くには、どう書けばよいですか。
条件分岐で書けます。
もし Arrive[i] > Finish[i-1] ならば Start[i] = Arrive[i]、そうでなければ Start[i] = Finish[i-1] です。
最大値の関数は「大きいほうを選ぶ条件分岐」を短く書いたものだと理解しておくと、どちらの形で出題されても対応できます。