当前位置:首页 > 洛谷 > 洛谷P2346四子连珠游戏最短步数BFS解法详解

洛谷P2346四子连珠游戏最短步数BFS解法详解

3周前 (06-23)

洛谷P2346四子连珠游戏最短步数BFS解法详解  BFS算法 最短路径算法 第1张

一、题目解读

洛谷P2346是一道经典的棋盘游戏问题,要求在一4x4黑白棋棋盘上,通过移动棋子使同色棋子形成四子一线(横、竖或对角线),计算达成目标所需的最少步数。题目考察BFS算法应用和状态空间搜索能力。

二、解题思路

状态表示:使用字符串存储棋盘状态,记录步数和当前执棋方

BFS核心:广度优先搜索保证找到最短路径

胜利判定:检查所有行、列和对角线是否存在四子一线

状态转移:对每个空格检查四周可移动的同色棋子

三、解题步骤

初始化队列,同时考虑黑白双方先手

每次取出队首状态检查是否达成目标

生成所有可能的下一个状态(移动有效棋子)

使用哈希表记录已访问状态避免重复计算

返回最先找到的解步数

四、完整代码

#include <iostream>
#include <queue>
#include <unordered_map>
#include <string>
#include <algorithm>
using namespace std;

// 定义棋盘状态结构体
struct State {
    string board;  // 棋盘状态字符串
    int steps;     // 到达该状态的步数
    bool isBlack;  // 当前该谁走棋
};

// 检查是否达到目标状态(四个一线)
bool isGoal(const string& board) {
    // 检查所有行
    for (int i = 0; i < 4; ++i) {
        if (board[i*4] != 'O' && board[i*4] == board[i*4+1] && 
            board[i*4] == board[i*4+2] && board[i*4] == board[i*4+3])
            return true;
    }
    
    // 检查所有列
    for (int i = 0; i < 4; ++i) {
        if (board[i] != 'O' && board[i] == board[i+4] && 
            board[i] == board[i+8] && board[i] == board[i+12])
            return true;
    }
    
    // 检查对角线
    if (board[0] != 'O' && board[0] == board[5] && 
        board[0] == board[10] && board[0] == board[15])
        return true;
    if (board[3] != 'O' && board[3] == board[6] && 
        board[3] == board[9] && board[3] == board[12])
        return true;
    
    return false;
}

// 获取所有可能的下一步状态
vector<State> getNextStates(const State& current) {
    vector<State> nextStates;
    const string& board = current.board;
    char currentPlayer = current.isBlack ? 'B' : 'W';
    
    // 找到所有空格位置
    vector<int> emptyPos;
    for (int i = 0; i < 16; ++i) {
        if (board[i] == 'O') emptyPos.push_back(i);
    }
    
    // 对于每个空格,检查四周可以移动过来的棋子
    for (int pos : emptyPos) {
        int row = pos / 4;
        int col = pos % 4;
        
        // 检查四个方向
        int dirs[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};
        for (auto& dir : dirs) {
            int newRow = row + dir[0];
            int newCol = col + dir[1];
            
            if (newRow >= 0 && newRow < 4 && newCol >= 0 && newCol < 4) {
                int newPos = newRow * 4 + newCol;
                if (board[newPos] == currentPlayer) {
                    // 可以移动这个棋子到空格
                    string newBoard = board;
                    swap(newBoard[newPos], newBoard[pos]);
                    nextStates.push_back({newBoard, current.steps + 1, !current.isBlack});
                }
            }
        }
    }
    
    return nextStates;
}

int bfs(const string& initialBoard) {
    queue<State> q;
    unordered_map<string, bool> visited;
    
    // 初始状态,黑方先走
    q.push({initialBoard, 0, true});
    // 白方先走的初始状态
    q.push({initialBoard, 0, false});
    visited[initialBoard + "1"] = true;  // 黑方先走的标记
    visited[initialBoard + "0"] = true;  // 白方先走的标记
    
    while (!q.empty()) {
        State current = q.front();
        q.pop();
        
        if (isGoal(current.board)) {
            return current.steps;
        }
        
        vector<State> nextStates = getNextStates(current);
        for (const State& next : nextStates) {
            string key = next.board + (next.isBlack ? "1" : "0");
            if (!visited.count(key)) {
                visited[key] = true;
                q.push(next);
            }
        }
    }
    
    return -1;  // 无解情况
}

int main() {
    string board;
    string line;
    
    // 读取4x4棋盘
    for (int i = 0; i < 4; ++i) {
        cin >> line;
        board += line;
    }
    
    int result = bfs(board);
    cout << result << endl;
    
    return 0;
}

五、总结

本解法通过BFS高效搜索状态空间,利用字符串表示棋盘状态,结合哈希去重,确保在最短步数内找到解。算法时间复杂度取决于有效状态数,空间复杂度通过哈希优化。

原创内容 转载请注明出处

分享给朋友:

相关文章

2022年蓝桥杯省赛B组扫雷(洛谷P8785)解题全解析:代码+思路+步骤详解

2022年蓝桥杯省赛B组扫雷(洛谷P8785)解题全解析:代码+思路+步骤详解

一、题目解读2022年蓝桥杯省赛B组机器人塔(洛谷P8785)是一道经典的算法题目,要求处理在一个二维平面上布置的炸雷与排雷火箭。炸雷具有爆炸半径,当排雷火箭引爆后,会触发周围范围内未被引爆的炸雷,形...

2024年蓝桥杯国赛A组题 九宫格全解析:基于BFS算法的代码实现与优化

2024年蓝桥杯国赛A组题 九宫格全解析:基于BFS算法的代码实现与优化

一、题目解读2024年蓝桥杯国A的九宫格题目(对应洛谷P10578)要求通过旋转九宫格中的2x2区域,实现从初始状态到目标状态的转换,并计算最小步数。该问题属于经典的图论搜索问题,需要高效的状态转换与...

洛谷1363题解法:虚拟坐标优化BFS解决循环迷宫问题(附代码详解)

洛谷1363题解法:虚拟坐标优化BFS解决循环迷宫问题(附代码详解)

一、题目解读洛谷1363题要求判断在给定大小的循环迷宫中,从起点出发是否可以通过移动到达多个不同的路径方向。迷宫由字符矩阵表示,'S'为起点,'#'为障碍物,其余为可通...

牛客13279题解:基于广度优先搜索(BFS)计算树高度的算法优化与代码实现

牛客13279题解:基于广度优先搜索(BFS)计算树高度的算法优化与代码实现

一、题目解读牛客13279题要求计算给定树的高度。树由n个节点组成,通过n-1条边连接,形成一棵有根树。题目核心在于高效求解树的高度,即从根节点到最深叶子节点的最长路径长度。需要理解树的结构特点,选择...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。