解题技巧:
1.将3*3矩阵的状态压缩成一个整数来表示,使用二进制位运算来进行状态转移。
2.使用广度优先搜索求最短路径,从1-9种状态转移进行尝试,保证第一次得到的答案是字典序最小的。
3.如果题目给出的状态为目标状态,也就是wwwwwwwww,则应该输出11(表示先按1位置一次,再按1位置一次)。
代码如下:
1 #include <iostream> 2 #include <string> 3 #include <queue> 4 #include <stack> 5 #include <vector> 6 using namespace std; 7 8 // 一个代表区域状态的整数的二进制表示中,0表示白色,1表示黑色. 9 10 const int STATES = 1 << 9; 11 bool visited[STATES]; 12 13 struct Elem { 14 int state; 15 int previous; 16 int op_num; 17 Elem(int s = 0, int p = 0, int on = 0) : state(s), previous(p), op_num(on) {} 18 }; 19 20 int goal = 0; // 目标状态,1-9全为白色. 21 22 vector<Elem> elems; 23 // Clicking field 1 inverts fields 1, 2, 4, 5 24 // Clicking field 2 inverts fields 1, 2, 3, 4, 5, 6 25 // Clicking field 3 inverts fields 2, 3, 5, 6 26 // Clicking 4 inverts fields 1, 2, 4, 5, 7, 8 27 // Clicking 5 inverts fields all fields 28 // Clicking 6 inverts fields 2, 3, 5, 6, 8, 9 29 // Clicking 7 inverts fields 4, 5, 7, 8 30 // Clicking 8 inverts fields 4, 5, 6, 7, 8, 9 31 // Clicking 9 inverts fields 5, 6, 8, 9 32 int click[10] = { 0, 27, 63, 54, 219, 511, 438, 216, 504, 432}; 33 34 void init() { 35 elems.clear(); 36 for (int i = 0; i < STATES; ++i) visited[i] = false; 37 } 38 39 int main() { 40 int n; cin >> n; 41 while (n--) { 42 string s; cin >> s; init(); 43 elems.push_back(Elem()); Elem &elem = elems.back(); 44 for (int i = 0; i < s.size(); ++i) { 45 if (s[i] == 'b') { 46 elem.state += 1 << i; 47 } 48 } 49 elem.previous = elem.op_num = -1; 50 if (elem.state != goal) visited[elem.state] = true; 51 int left = 0, right = 1; 52 bool find = false; 53 while (left < right && !find) { 54 for (int i = 1; i <= 9 && !find; ++i) { 55 Elem &e = elems[left]; 56 Elem next_e; 57 next_e.state = e.state ^ click[i]; 58 next_e.previous = left; 59 next_e.op_num = i; 60 if (!visited[next_e.state]) { 61 visited[next_e.state] = true; 62 elems.push_back(next_e); ++right; 63 } 64 if (next_e.state == goal) { 65 find = true; 66 } 67 } 68 ++left; 69 } 70 stack<int> st; 71 int cur = right - 1; 72 while (cur != 0) { 73 st.push(elems[cur].op_num); 74 cur = elems[cur].previous; 75 } 76 while (!st.empty()) { 77 cout << st.top(); st.pop(); 78 } 79 cout << endl; 80 } 81 82 return 0; 83 }