AOJ1302 Twenty Questions
コンテスト後の懇親会での議論を思い出しながら書いてみた。
Source
ACM/ICPC Asia Regional 2009 Tokyo Site: Problem H
解法
{ objectの部分集合 => 最適解 }をメモ再帰で求める。部分集合なので状態数は一見して最大 2^N (N = 128) になりそうだけど、質問を基準に考えると 2^M (M = 11) 程度にしかならないことがわかる。
まさかこんなに簡単に書けるとは思わなかった。Bより簡単だ!
#include <iostream> #include <map> #include <vector> #include <algorithm> #define REP(i,e) for(int i=0;i<(int)(e);i++) using namespace std; typedef vector<int> vint; enum{ N=128, M=11 }; int n,m; char v[N][M]; map<vint,int> ans; int rec(vint& t){ if(t.size()==1) return 0; if(!ans.count(t)){ int res=1<<20; REP(j,m){ vint a,b; REP(i,t.size()) v[t[i]][j]=='0' ? a.push_back(t[i]) : b.push_back(t[i]); if(!a.empty()&&!b.empty()) res=min(res,max(rec(a),rec(b))+1); } return ans[t]=res; } return ans[t]; } int main(){ while(cin >> m >> n && n|m){ REP(i,n) REP(j,m) cin >> v[i][j]; vint t(n); REP(i,n) t[i]=i; ans.clear(); cout << rec(t) << endl; } }