Ranking (as of 2013-07-13): 148 out of 708
Language: C++
/* UVa 704 - Colour Hash To build using Visual Studio 2008: cl -EHsc -O2 colour_hash.bfs.cache.cpp */ #include <iostream> #include <map> #include <deque> #include <queue> #ifdef __ELAPSED_TIME__ #include <ctime> #endif using namespace std; enum rotation { // rotations unknown = 0, left_clockwise = 1, // left wheel clockwise right_clockwise = 2, // right wheel clockwise left_counterclockwise = 3, // left wheel counterclockwise right_counterclockwise = 4, // right wheel counterclockwise }; typedef pair<unsigned long long, unsigned long long> wheels; /* wheels.first consists of left wheel numbers and wheels.second consists of right wheel numbers. i-th (i >= 0) number occupies between (47 - i * 4)-th and (44 - i * 4)-th bits of wheels.first/wheels.second. The final condition of wheels are represented as wheels(0x034305650121, 0x078709a90121). */ const size_t numbers_per_wheel = 12; // count of numbers (triangle/separator) per wheel const size_t max_movements = 16; // max. number of movements const wheels wheels_solved(0x034305650121, 0x078709a90121); // the final condition of wheels map< wheels, deque<char> > latter_half_cache; // key is a state, value is the sequence of movements // that leads to the final state wheels rotate_wheel(rotation r, const wheels& w) { const unsigned long long mask_8_bits = 0xff, mask_12_bits = 0xfff; unsigned long long left = w.first, right = w.second; unsigned long long b; switch (r) { case left_clockwise: // left wheel clockwise b = left & mask_8_bits; left >>= 8; left |= b << 40; right &= ~mask_12_bits; right |= left & mask_12_bits; break; case right_clockwise: // right wheel clockwise b = (right & mask_8_bits << 40) >> 40; right &= ~(mask_8_bits << 40); right <<= 8; right |= b; left &= ~mask_12_bits; left |= right & mask_12_bits; break; case left_counterclockwise: // left wheel counterclockwise b = (left & mask_8_bits << 40) >> 40; left &= ~(mask_8_bits << 40); left <<= 8; left |= b; right &= ~mask_12_bits; right |= left & mask_12_bits; break; case right_counterclockwise: // right wheel counterclockwise b = right & mask_8_bits; right >>= 8; right |= b << 40; left &= ~mask_12_bits; left |= right & mask_12_bits; break; } return wheels(left, right); } bool rotate_wheel_and_cache(rotation r, const wheels& w, const deque<char>& m, queue<wheels>& q) { wheels nw = rotate_wheel(r, w); if (latter_half_cache.find(nw) != latter_half_cache.end()) return false; rotation nr; switch (r) { case left_clockwise: nr = left_counterclockwise; break; case right_clockwise: nr = right_counterclockwise; break; case left_counterclockwise: nr = left_clockwise; break; case right_counterclockwise: nr = right_clockwise; break; } deque<char> nm(m); nm.push_front(nr); latter_half_cache.insert(make_pair(nw, nm)); q.push(nw); return true; } void generate_state_cache() { /* Starting from the final state (configuration), do a BFS (Breadth First Search) and cache the states that can be reached in 8 steps (movements) or less. */ latter_half_cache.insert(make_pair(wheels_solved, deque<char>())); queue<wheels> q; q.push(wheels_solved); while (!q.empty()) { wheels w = q.front(); q.pop(); deque<char> m = latter_half_cache[w]; if (m.size() < max_movements / 2) { for (int r = left_clockwise; r <= right_counterclockwise; r++) rotate_wheel_and_cache(static_cast<rotation>(r), w, m, q); } } #ifdef DEBUG cerr << "number of latter_half_cache entries = " << latter_half_cache.size() << endl; #endif } bool rotate_wheel_and_cache(rotation r, const wheels& w, const deque<char>& m, queue<wheels>& q, map< wheels, deque<char> >& cache) { wheels nw = rotate_wheel(r, w); if (cache.find(nw) != cache.end()) return false; deque<char> nm(m); nm.push_back(r); cache.insert(make_pair(nw, nm)); q.push(nw); return true; } bool solve_state(const wheels& w, deque<char>& mv) { bool solved = false; map< wheels, deque<char> > cache; cache.insert(make_pair(w, deque<char>())); queue<wheels> q; q.push(w); map< wheels, deque<char> >::const_iterator lhce = latter_half_cache.end(); while (!q.empty()) { wheels w = q.front(); q.pop(); deque<char>& m = cache[w]; map< wheels, deque<char> >::const_iterator lhci = latter_half_cache.find(w); if (lhci != lhce) { solved = true; mv = m; mv.insert(mv.end(), lhci->second.begin(), lhci->second.end()); break; } else if (m.size() < max_movements / 2) { for (int r = left_clockwise; r <= right_counterclockwise; r++) rotate_wheel_and_cache(static_cast<rotation>(r), w, m, q, cache); } } return solved; } int main() { #ifdef __ELAPSED_TIME__ clock_t start = clock(); #endif generate_state_cache(); int n; cin >> n; while (n--) { int nr; wheels w(0, 0); for (size_t i = 0; i < numbers_per_wheel; i++) { cin >> nr; w.first <<= 4; w.first |= nr; } for (size_t i = 0; i < numbers_per_wheel; i++) { cin >> nr; w.second <<= 4; w.second |= nr; } deque<char> mv; if (solve_state(w, mv)) { if (mv.empty()) cout << "PUZZLE ALREADY SOLVED\n"; else { for (deque<char>::const_iterator i = mv.begin(), e = mv.end(); i != e; ++i) cout << static_cast<int>(*i); cout << endl; } } else cout << "NO SOLUTION WAS FOUND IN 16 STEPS\n"; } #ifdef __ELAPSED_TIME__ cerr << "elapsed time = " << static_cast<double>(clock() - start) / CLOCKS_PER_SEC << " sec.\n"; #endif return 0; }
No comments:
Post a Comment