SOJ 1048.Inverso

解题技巧:

  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 }

 

posted @ 2016-01-09 13:18  MchCyLh  阅读(196)  评论(0编辑  收藏  举报