辞書順最小は先頭から決める。
1つ以上の答えがあるそうなので、順に0を割り当てて試す。
ある場所に0を割り当ててマトリックスを作れないのならば、そこに1を入れればいい。
マトリックスになるかどうかは、2部マッチングをすればよい。
struct E { int src, dst; E (int s, int d) : src(s), dst(d) {} }; const int N = 30 * 2 + 5; vector<E> g[N]; void add_edge(int src, int dst) { g[src].push_back(E(src, dst)); g[dst].push_back(E(dst, src)); return ; } int match[N]; bool vis[N]; bool rec(int curr) { vis[curr] = true; for (int i = 0; i < g[curr].size(); ++i) { int next = g[curr][i].dst; int w = match[next]; if (w < 0 || (!vis[w] && rec(w))) { match[curr] = next; match[next] = curr; return true; } } return false; } int make_graph(vector<string> R, vector<string> C) { fill(g, g + N, vector<E>()); const int H = R.size(); const int W = C.size(); for (int i = 0; i < W; ++i) { for (int j = 0; j < W; ++j) { bool flg = true; for (int k = 0; k < H; ++k) { if (R[k][i] == '?') continue; if (C[j][k] == '?') continue; flg = flg && (R[k][i] == C[j][k]); } if (flg) add_edge(i, j + W); } } return W + W; } int matching(vector<string> R, vector<string> C) { const int V = make_graph(R, C); int res = 0; fill(match, match + N, -1); for (int i = 0; i < V; ++i) { if (match[i] < 0) { fill(vis, vis + N, false); res += rec(i); } } return res; } class P8XMatrixRecovery { public: vector <string> solve(vector <string> R, vector <string> C) { const int H = R.size(); const int W = C.size(); for (int i = 0; i < H; ++i) { for (int j = 0; j < W; ++j) { if (R[i][j] == '?') { R[i][j] = '0'; if (matching(R, C) != W) R[i][j] = '1'; } } } return R; } };