公式

C - スイッチパネル / Switch Panel 解説 by physics0523


bit全探索 を用いることで、この問題に正解できます。

各スイッチをひとつの整数で表現します。具体的には、電灯 \(k\) を切り替える機能がある時に \(k\) bit 目を立てます。
すると、スイッチを押した後の電灯の状態は、押したスイッチに対応する整数すべての XOR(排他的論理和) で表現できます。
なので、スイッチの押し方を \(2^M\) 通り試します。各試行についてスイッチを押す回数は高々 \(M\) 回で、点灯している電灯の個数を数えるには総 XOR の popcount (立っている bit の個数) を求めればよいです。

本解法の時間計算量は \(O(M2^M)\) です。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  int N,M,K;
  cin >> N >> M >> K;
  vector<int> sw(M,0);
  for(int i=0;i<M;i++){
    int c;
    cin >> c;
    for(int j=0;j<c;j++){
      int s;
      cin >> s;
      sw[i]|=(1<<s);
    }
  }
  int res=1e9;
  for(int i=0;i<(1<<M);i++){
    int cur=0,cnt=0;
    for(int j=0;j<M;j++){
      if(i&(1<<j)){
        cur^=sw[j];
        cnt++;
      }
    }
    if(__builtin_popcount(cur)==K){res=min(res,cnt);}
  }
  if(res>5e8){res=-1;}
  cout << res << "\n";
  return 0;
}

投稿日時:
最終更新: