• 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 }
  • 相关阅读:
    vue 封装 全局弹窗 js-dom
    vue 封装时间戳 用过滤方法封装
    前端上传img 并且添加水印
    原生ajax 封装
    vue filters 过滤用法 时间戳方法
    node+mysql+vue 搭建前后端分离基础框架
    基于jq div拉拽功能
    进程间通信方式+线程间通信方式
    只能生成栈对象和只能生成堆对象
    linux的基础命令行和shell的区别
  • 原文地址:https://www.cnblogs.com/mchcylh/p/5116207.html
Copyright © 2020-2023  润新知