JAG 夏合宿 2015 Day2 D: 真っ暗な部屋

解法

最初 M 人の人が、それぞれの暗い部屋にいるとする。これらの人たちを全員明るい部屋に連れていくことを考える。各状態について、遷移の仕方がk通りある。全員が暗い部屋にいる状態から、全員が明るい部屋にいる状態へ移動する、最短経路問題として考える。

コード

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N, M, K;
  cin >> N >> M >> K;
  vector<int> D(M);
  for (int i = 0; i < M; ++i) {
    cin >> D[i];
    D[i]--;
  }

  vector<int> darkness(N, -1);
  for (int i = 0; i < M; ++i) {
    darkness[D[i]] = i;
  }

  vector<vector<int>> v(N, vector<int>(K));
  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < K; ++j) {
      cin >> v[i][j];
      v[i][j]--;
    }
  }

  vector<int> dist((1 << M), 1e9);
  queue<int> que;
  que.push((1 << M) - 1);
  dist[(1 << M) - 1] = 0;
  while (!que.empty()) {
    int now = que.front();
    que.pop();
    for (int k = 0; k < K; ++k) {
      int next_mask = 0;
      for (int m = 0; m < M; ++m) {
        if (now & (1 << m)) {
          int next = v[D[m]][k];
          if (darkness[next] < 0) continue;
          next_mask |= (1 << darkness[next]);
        }
      }
      if (dist[next_mask] > dist[now] + 1) {
        dist[next_mask] = dist[now] + 1;
        que.push(next_mask);
        if (next_mask == 0) {
          cout << dist[0] << endl;
          return 0;
        }
      }
    }
  }
}