zoukankan      html  css  js  c++  java
  • AcWing 845. 八数码

    题目传送门

    一、理解与感悟

    1. 为什么将二维转一维?
      输入的是一个一维数据,就像是一个字符串。二维数组如果想对比每一次走完的棋盘是否一致,需要双重循环,比较麻烦,所以想出了一个用一维模拟二维的方法。

    2. 二维怎么转一维?
      一维下标=tx * 3 + ty

    以行号、列号下标从(0)开始为例,就是行号( imes 3 +) 列号,比如:
    行号为(1)(第二行),列号为(1)(第二列),那么(1 imes 3+1=4),就是在一维中是第(5)个(下标从(0)开始)。

    1. 一维如何还原成二维?
      int x = k / 3, y = k % 3;

    二、完整代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int bfs(string s) {
        //终点的样子
        string end = "12345678x";
        //广度搜索套路
        queue<string> q;
        //将当前棋盘入队列
        q.push(s);
        //记录距离
        unordered_map<string, int> d;
        d[s] = 0; //s节点的距离是0,就是无需变动
        //dx数组
        int dx[] = {-1, 0, 1, 0};
        int dy[] = {0, 1, 0, -1};
    
        while (!q.empty()) {
            auto t = q.front();
            q.pop();
            //距离
            int dist = d[t];
            //判断是不是到目标值了,这里就能看出字符串模拟的好处了,要不就是两个二维数组的双重循环对比,麻烦。
            if (t == end) return dist;
    
            //状态转移
            int k = t.find('x');
            //一维数组转化为二维数组的坐标,是一个常用技巧
            //除3就是行,模3就是列,x,y下标从0开始
            int x = k / 3, y = k % 3;
            //四个方向
            for (int i = 0; i < 4; i++) {
                //走一步后的坐标
                int tx = x + dx[i], ty = y + dy[i];
                //不出界
                if (tx >= 0 && tx < 3 && ty >= 0 && ty < 3) {
                    //调整位置
                    //二维数组转一维数组的技巧
                    swap(t[k], t[tx * 3 + ty]);
                    if (!d.count(t)) {      //这个位置以前没有人走过
                        d[t] = dist + 1;    //距离需要+1
                        q.push(t);          //放入队列
                    }
                    swap(t[tx * 3 + ty], t[k]);
                }
            }
        }
        return -1;
    }
    
    int main() {
        //读入优化
        ios::sync_with_stdio(false);
    
        //开始的棋盘(字符之间用空格隔开,所以不能用string,需要cin+char解决)
        string s;
        char c;
        for (int i = 1; i <= 9; i++) {
            cin >> c;
            s += c;
        }
        //广度优先搜索
        cout << bfs(s) << endl;
    
        return 0;
    }
    
  • 相关阅读:
    闲记
    网络数据校验随笔(1)
    [转载]各种在线api地址
    WebLogic Server
    接口和抽象类的区别
    PowerBuilder连接数据库
    Entity Framework(实体框架 EF)
    SQL Server附加数据库提示“版本为661,无法打开,支持655版本……”
    实习总结
    此页状态无效,可能已损坏
  • 原文地址:https://www.cnblogs.com/littlehb/p/15307374.html
Copyright © 2011-2022 走看看