/** * ICPC Central Europe Regional Contest 2018 * Problem Solution: Lord of the Kings * * @author Josef Cibulka */ #include #include #include #include #include #include #include #include #include #define MAXTERM 12 #define MAXDIM 16 using namespace std; int n, m; int vid(int r, int c) { if(r<0 || r>=n || c<0 || c>=m) return -1; return r * m + c; } class Graph { public: int vcnt; vector> neighs; vector terms; vector> best_sol; vector> best_sola; vector> known_dsts; explicit Graph(int vcnt_) : vcnt(vcnt_), neighs(vcnt_, vector()), known_dsts(vcnt_, vector(vcnt_, -2)) { } void precount_dst(int u) { deque q; vector dst(vcnt, -1); q.push_back(u); dst[u] = 0; while(q.size() > 0) { int fr = q.front(); q.pop_front(); for(int t : neighs[fr]) { if(dst[t] >= 0) continue; dst[t] = dst[fr] + 1; known_dsts[u][t] = known_dsts[t][u] = dst[t]; q.push_back(t); } } known_dsts[u] = dst; } void precount_all_dst() { for(int u = 0; u < vcnt; ++u) precount_dst(u); } int count_dst(int u, int v) { return known_dsts[u][v]; } vector subsub(vector& sub, int ind) { vector ret; for(char b : sub) { if(!b) { ret.push_back(b); } else { char newb = (ind&1); ind >>= 1; ret.push_back(newb); } } return ret; } int subind(vector& sub) { int ret = 0; for(char b : sub) ret = ((ret<<1) + b); return ret; } int solve_in_root(vector& sub, int ind, int root) { int known = best_sola[ind][root]; if(known != -2) return known; int subsize = 0; for (size_t i = 0; i < sub.size(); ++i) if(sub[i]) ++subsize; vector best = vector(vcnt, -1); for(int i = 1; i < (1< icompl) continue; vector suba = subsub(sub, i); vector subb = subsub(sub, icompl); for (int root2 = 0; root2 < vcnt; ++root2) { int cura = solve(suba, root2); int curb = solve(subb, root2); if (cura == -1 || curb == -1) continue; int cur = cura + curb - 1; if(best[root2] == -1 || (cur != -1 && cur < best[root2])) best[root2] = cur; } } best_sola[ind] = best; return best[root]; } int solve(vector& sub, int root) { int ind = subind(sub); int known = best_sol[ind][root]; if(known != -2) return known; int subsize = 0; int member = -1; for (size_t i = 0; i < sub.size(); ++i) if(sub[i]) { ++subsize; member = i; } if(subsize == 1) { int sol = 1; if(root != terms[member]) { int dst = count_dst(terms[member], root); if(dst == -1) sol = -1; else sol = dst + 1; } best_sol[ind][root] = sol; return sol; } int best = -1; for(int root2 = 0; root2 < vcnt; ++root2) { int dst = count_dst(root, root2); int cur = solve_in_root(sub, ind, root2); if (cur == -1 || dst == -1) continue; cur += dst; if(best == -1 || (cur != -1 && cur < best)) best = cur; } best_sol[ind][root] = best; return best; } int steiner(vector terms_) { terms = terms_; best_sol.resize(1<(vcnt, -2)); best_sola.resize(1<(vcnt, -2)); vector sub(terms.size(), true); int best = -1; for(int root = 0; root < vcnt; ++root) { int cur = solve(sub, root); if(best == -1 || (cur != -1 && cur < best)) best = cur; } return best; } }; Graph build(int type) { Graph g(n*m); for (int r = 0; r < n; ++r) for (int c = 0; c < m; ++c) { int id = vid(r,c); if(type == 'K') { for(int i=-1; i<=1; ++i) for(int j=-1; j<=1; ++j) { if (i==0 && j==0) continue; int nid = vid(r + i, c + j); if(nid != -1) g.neighs[id].push_back(nid); } } if(type == 'N') { for(int i=-2; i<=2; ++i) for(int j=-2; j<=2; ++j) { if (i==0 || j==0 || abs(i) == abs(j)) continue; int nid = vid(r + i, c + j); if(nid != -1) g.neighs[id].push_back(nid); } } if(type == 'B' || type == 'Q') { for(int i=-n; i<=n; ++i) for(int j : vector {-i, i}) { if (i==0) continue; int nid = vid(r + i, c + j); if(nid != -1) g.neighs[id].push_back(nid); } } if(type == 'R' || type == 'Q') { for(int i=-n; i<=n; ++i) { if (i==0) continue; int nid = vid(r + i, c); if(nid != -1) g.neighs[id].push_back(nid); } for(int j=-m; j<=m; ++j) { if (j==0) continue; int nid = vid(r, c + j); if(nid != -1) g.neighs[id].push_back(nid); } } } g.precount_all_dst(); return g; } int main(void) { cin >> n >> m; int r, c; char type; cin >> r >> c >> type; vector terms; terms.push_back(vid(r-1, c-1)); int ccnt; cin >> ccnt; for (int i = 0; i < ccnt; ++i) { cin >> r >> c; terms.push_back(vid(r-1, c-1)); } Graph g = build(type); int res = g.steiner(terms); if(res != -1) --res; cout << res << endl; return 0; }