倉庫の 電灯を 全部点けるスイッチ
- 全探索
- 問題 11
- ふつう
- 目安 31 分
押すたびに
本番の
入力は
問題
倉庫に 1 から M までの
いまの
入力の形式
N M
S
k_1 c_1,1 c_1,2 ... c_1,k_1
k_2 c_2,1 c_2,2 ... c_2,k_2
...
k_N c_N,1 c_N,2 ... c_N,k_N1 行目に
出力の形式
押す回数の
制約
- N は 1 以上 16 以下です
- M は 1 以上 20 以下です
- S は 0 と 1 だけからなる
長さ M の 文字列です - k_i は 1 以上 M 以下です
- 電灯の
番号 c_i,1 から c_i,k_i は 1 以上 M 以下で、 小さい 順に 並び、 同じ 番号は ありません
入力と出力の例
例 1
電灯 1 と
入力
3 4 1010 2 1 2 2 1 4 2 3 4
出力
2
例 2
スイッチ 1 も
入力
2 2 01 2 1 2 2 1 2
出力
-1
例 3
最初から
入力
1 3 111 1 2
出力
0
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
全部の
先に
解答
電灯の
Python
Python
import sys
data = sys.stdin.read().split()
n, m = int(data[0]), int(data[1])
start = 0
for j, ch in enumerate(data[2]):
if ch == "1":
start |= 1 << j
masks = []
pos = 3
for i in range(n):
k = int(data[pos])
mask = 0
for c in data[pos + 1:pos + 1 + k]:
mask |= 1 << (int(c) - 1)
masks.append(mask)
pos += 1 + k
full = (1 << m) - 1
best = -1
for pressed in range(1 << n):
state = start
for i in range(n):
if pressed >> i & 1:
state ^= masks[i]
if state == full:
count = bin(pressed).count("1")
if best == -1 or count < best:
best = count
print(best)JavaScript
JavaScript
const data = require("fs").readFileSync(0, "utf8").split(/\s+/).filter(Boolean);
const n = Number(data[0]);
const m = Number(data[1]);
let start = 0;
for (let j = 0; j < m; j++) {
if (data[2][j] === "1") start |= 1 << j;
}
const masks = [];
let pos = 3;
for (let i = 0; i < n; i++) {
const k = Number(data[pos]);
let mask = 0;
for (let t = 1; t <= k; t++) mask |= 1 << (Number(data[pos + t]) - 1);
masks.push(mask);
pos += 1 + k;
}
const full = (1 << m) - 1;
let best = -1;
for (let pressed = 0; pressed < 1 << n; pressed++) {
let state = start;
let count = 0;
for (let i = 0; i < n; i++) {
if ((pressed >> i) & 1) {
state ^= masks[i];
count++;
}
}
if (state === full && (best === -1 || count < best)) best = count;
}
console.log(best);計算量
時間は O(2^N × N) です。
よく ある間違い
- 押す順番まで
全部試してしまう。 入れ替えは 順番に よらないので、 押すか 押さないかの 組だけで足ります - 同じ
スイッチを 2 回以上押す 場合まで 数えようとして、 終わらない 探索を 書く。 2 回押すのは 押さないのと同じです - 電灯の
番号は 1 から、 ビットの 桁は 0 から 数える ことを 忘れて、 1 つずれる。 電灯 j は 1 << (j - 1)です - 最初から
全部点いている ときに 0 ではなく -1 を 出す。 押し方 b = 0 (何も 押さない ) も 試す範囲に入れます
解答を動かした版 Python 3.12.14Node.js 22.23.4確認日 2026/10/31