Ranking (as of 2013-03-24): 142
Language: C++
/* UVa 321 - The New Villa To build using Visual Studio 2008: cl -EHsc -O2 the_new_villa.cpp */ #include <iostream> #include <queue> #include <cstring> using namespace std; const int nr_rooms_max = 10; const int room_shift = 1 << nr_rooms_max; const int lights_mask = room_shift - 1; bool doors[nr_rooms_max][nr_rooms_max]; // doors[i][j] is true if there is a door between i-th and j-th rooms int switches[nr_rooms_max]; // switches[i] is the bitmap of lights of the i-th room, in which j-th bit of // switches[i] is set if there is a switch for the light of j-th room // in the i-th room bool visited[nr_rooms_max * room_shift]; // visited[i] is true if the state of i has already been visited int parents[nr_rooms_max * room_shift]; // parents[i] is the i-th parent state bool push_state(int current, int next, queue<int>& q) { if (!visited[next]) { visited[next] = true; parents[next] = current; q.push(next); return true; } else return false; } bool bfs(int nr_rooms, int end_state) { /* Each state consists of two fields: bit 0 - bit 9: bitmap of lights where i-th bit is set if the i-th room's light is on bit 10 - bit 13: room index Do a breadth-first-search between transferable states. */ queue<int> q; int state = 1; // light is on at the first room (hallway) visited[state] = true; q.push(state); while (!q.empty()) { int current = q.front(); q.pop(); if (current == end_state) return true; int r = current >> nr_rooms_max, lights = current & lights_mask; for (int i = 0, l = 1; i < nr_rooms_max; i++, l <<= 1) if (doors[r][i] && lights & l) // since i-th rooms has already been lit, we can move to it push_state(current, i << nr_rooms_max | lights, q); for (int i = 0, l = 1; i < nr_rooms; i++, l <<= 1) if (switches[r] & l) { // r-th room has a switch of the light for i-th room int next = -1; if (lights & l) { if (r != i) // the light can be switched to off next = r << nr_rooms_max | lights & ~l; } else // the light can be switched to on next = r << nr_rooms_max | lights | l; if (next != -1) push_state(current, next, q); } } return false; } int get_number_of_steps(int end_state) { int nr_steps = 0; for (int p = parents[end_state]; p != -1; p = parents[p]) nr_steps++; return nr_steps; } void print_steps(int current, int next) { if (current == -1) return; print_steps(parents[current], current); int i = current ^ next; if (i & lights_mask) { int l = 1; for (int j = i >> 1; j; j >>= 1) l++; if (i & next) cout << "- Switch on light in room " << l << ".\n"; else cout << "- Switch off light in room " << l << ".\n"; } else { int r = next >> nr_rooms_max; cout << "- Move to room " << r + 1 << ".\n"; } } int main() { for (int v = 1; ; v++) { int r, d, s; cin >> r >> d >> s; if (!r && !d && !s) break; memset(doors, 0, sizeof(doors)); memset(switches, 0, sizeof(switches)); for (int i = 0; i < d; i++) { int j, k; cin >> j >> k; j--; k--; doors[j][k] = doors[k][j] = true; } for (int i = 0; i < s; i++) { int j, k; cin >> j >> k; j--; k--; switches[j] |= 1 << k; } memset(visited, 0, sizeof(visited)); memset(parents, -1, sizeof(parents)); int end_state = (r - 1) << nr_rooms_max | 1 << (r - 1); bool successful = bfs(r, end_state); cout << "Villa #" << v << endl; if (successful) { cout << "The problem can be solved in " << get_number_of_steps(end_state) << " steps:\n"; print_steps(parents[end_state], end_state); } else cout << "The problem cannot be solved.\n"; cout << endl; } return 0; }
No comments:
Post a Comment