leetcode 773. Sliding Puzzle

56 篇文章 0 订阅
53 篇文章 0 订阅

写在前面

好久没写算法题题解了,实在太忙了。每周的contest都有在做,本周的contest 第二题第三题都算比较有趣的题目,也都A了,先整理一下第三题的解题思路。

题目描述

On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0.

A move consists of choosing 0 and a 4-directionally adjacent number and swapping it.

The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]].

Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1.

Examples:

Input: board = [[1,2,3],[4,0,5]]
Output: 1
Explanation: Swap the 0 and the 5 in one move.
Input: board = [[1,2,3],[5,4,0]]
Output: -1
Explanation: No number of moves will make the board solved.
Input: board = [[4,1,2],[5,0,3]]
Output: 5
Explanation: 5 is the smallest number of moves that solves the board.
An example path:
After move 0: [[4,1,2],[5,0,3]]
After move 1: [[4,1,2],[0,5,3]]
After move 2: [[0,1,2],[4,5,3]]
After move 3: [[1,0,2],[4,5,3]]
After move 4: [[1,2,0],[4,5,3]]
After move 5: [[1,2,3],[4,5,0]]
Input: board = [[3,2,4],[1,5,0]]
Output: 14
Note:

board will be a 2 x 3 array as described above.
board[i][j] will be a permutation of [0, 1, 2, 3, 4, 5].

解题思路

拼图问题,其实就是八数码问题,给定一个可移动的数字,该数字每次只能朝四个方向移动,问最少经过多少次移动能够完成拼图(给定的序列)。刚开始看到的时候完全没思路,后来想到了用BFS来解,BFS相当于一种暴力搜索,每次去搜索所有可能的结果(对本题来说就是三个方向),直到满足条件或退出。事实上看了一些博客了解到更好的解法是A*,这里先不考虑A*,在后面的寻路算法的实现中会写A*的实现。关于BFS的实现,自我感觉自己的写法应该是比较优秀的写法,相对于网上的很多实现来讲,更加简洁,也符合C++的标准。

代码实现

class Solution {
public:
    int slidingPuzzle(vector<vector<int>>& board) {
        string des = "123450";
        string init;
        for(int i = 0;i<board.size();++i)
            for(int j = 0;j<board[0].size();++j) {
                init+=to_string(board[i][j]);
            }
        if(init == des) return 0;
        queue<string> q;
        vector<pair<int,int>> dir{{1,0},{-1,0},{0,1},{0,-1}};
        unordered_set<string> mSet;
        mSet.insert(init);
        q.push(init);
        int moves = 0;
        while(!q.empty()) {
            int size = q.size();
            for(int i = 0;i<size;++i) {
                auto t = q.front();
                q.pop();
                int pos = t.find('0');

                int rpx = pos/3;
                int rpy = pos%3;
                // 3 dir
                for(auto&v:dir) {
                    int x = rpx+v.first;
                    int y = rpy+v.second;

                    if(x>=0&&x<2&&y>=0&&y<3) {
                        auto r = x*3+y;
                        string n = t;
                        swap(n[pos],n[r]);
                        if(n==des) return ++moves;
                        if(mSet.find(n)==mSet.end()) {

                            mSet.insert(n);
                            q.push(n);
                        }
                    }
                }
            }
            moves++;
        }
        return -1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值