/* Quick Search, MCPC 2010 Problem G, C++ solution by Michael Goldwasser */ #include #include #include #include #include #include using namespace std; //#define DEBUG const int MAX_SITES(20); // globals are our friends fstream fin("search.in"); int numSites, numPolice, numEdges; vector graph[MAX_SITES]; // utility function bool next_setting(vector& choices, vector& limits) { int k=choices.size(); do { --k; if (choices[k] < limits[k]-1) { choices[k]++; return true; } else choices[k] = 0; } while (k > 0); return false; } class State { private: vector visited; // locations that have already been visited vector police; // stored in sorted order int depth; public: State(int s, int n) : visited(s,false), police(n,0), depth(0) { visited[0] = true; } int getDepth() const { return depth;} vector neighbors() const { vector neigh; vector edgeChoice(numPolice,0); vector choiceCounts(numPolice); for (int k=0; k code() const { // computes a unique code to identify a state. We use two ints, // where first is the binary value based on 'visited' (but // ignoring site A which is always visted) , and the second is the // "base b" value based on police vector, where 'b' is the number // of sites. int first = 0; for (int k=1; k < visited.size(); k++) // intentionally ignore 'A' as its always covered if (visited[k]) first += 1<<(visited.size() - 1 - k); int second(0); int digit = 1; for (int k=0; k < police.size(); k++) { second += police[k] * digit; digit *= numSites; } return make_pair(first,second); } #ifdef DEBUG void dump() const { cout << "visited: "; for (int k=0; k < visited.size(); k++) // intentionally ignore 'A' as its always covered if (visited[k]) cout << char('A' + k); cout << endl; cout << "police: "; for (int k=0; k < police.size(); k++) cout << char('A' + police[k]); cout << endl; } #endif }; int solve() { set > familiar; queue fringe; State initial(numSites, numPolice); fringe.push(initial); familiar.insert(initial.code()); while (fringe.size() > 0) { State next(fringe.front()); fringe.pop(); #ifdef DEBUG cout << "Considering fringe state:" << endl; next.dump(); #endif vector others = next.neighbors(); for (int k=0; k < others.size(); k++) { pair id = others[k].code(); if (familiar.find(id) == familiar.end()) { // new state familiar.insert(id); if (others[k].solved()) return others[k].getDepth(); fringe.push(others[k]); } } } cout << "Unsolvable" << endl; // hopefully never happens } int main() { while (true) { fin >> numSites; if (numSites==0) break; // all done fin >> numPolice >> numEdges; for (int k=0; k < numSites; k++) graph[k].clear(); string edge; for (int k=0; k> edge; graph[edge[0]-'A'].push_back(edge[1]-'A'); graph[edge[1]-'A'].push_back(edge[0]-'A'); } cout << solve() << endl; } }