《P1379 八数码难题》

题目描述

在 3×3 的棋盘上,摆有八个棋子,每个棋子上标有 1 至 8 的某一数字。棋盘中留有一个空格,空格用 0 来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为 123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入格式

输入初始状态,一行九个数字,空格用 0 表示。

输出格式

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数。保证测试数据中无特殊无法到达目标状态数据。

输入输出样例

输入 #1复制

283104765

输出 #1复制

4

说明/提示

样例解释

《P1379 八数码难题》_第1张图片

图中标有 0 的是空格。绿色格子是空格所在位置,橙色格子是下一步可以移动到空格的位置。如图所示,用四步可以达到目标状态。

并且可以证明,不存在更优的策略。

代码实现:

#include
#include
#include
#include
#include
using namespace std;

// 四个方向:上、右、下、左
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};

// 检查输入字符串是否为合法的9位数字且包含0-8
bool isValidInput(const string& input) {
    if (input.length() != 9) return false;
    
    bool digits[9] = {false};
    // 替换为传统for循环
    for (int i = 0; i < input.length(); i++) {
        char c = input[i];
        if (c < '0' || c > '8') return false;
        int digit = c - '0';
        if (digits[digit]) return false; // 重复数字
        digits[digit] = true;
    }
    return true;
}

// 将字符串状态转换为二维数组中的位置
pair findZero(const string& state) {
    int pos = state.find('0');
    return {pos / 3, pos % 3};
}

// BFS求解最小步数
int bfs(string start, string target) {
    if (start == target) return 0;
    
    queue q;
    map dist;
    
    q.push(start);
    dist[start] = 0;
    
    while (!q.empty()) {
        string current = q.front();
        q.pop();
        
        pair zeroPos = findZero(current);
        int x = zeroPos.first, y = zeroPos.second;
        
        // 尝试四个方向的移动
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            
            // 检查新位置是否合法
            if (nx >= 0 && nx < 3 && ny >= 0 && ny < 3) {
                // 计算0的新位置在字符串中的索引
                int newZeroIdx = nx * 3 + ny;
                int oldZeroIdx = x * 3 + y;
                
                // 生成新状态
                string next = current;
                swap(next[oldZeroIdx], next[newZeroIdx]);
                
                // 如果新状态未访问过或找到更短路径
                if (dist.find(next) == dist.end()) {
                    dist[next] = dist[current] + 1;
                    
                    // 检查是否达到目标
                    if (next == target) return dist[next];
                    
                    q.push(next);
                }
            }
        }
    }
    
    return -1; // 无法到达目标状态(题目保证不会出现)
}

int main() {
    string start, target = "123804765";
    
    // 输入验证
    do {
       // cout << "请输入初始状态(9位数字,空格用0表示): ";
        cin >> start;
        
        if (!isValidInput(start)) {
            cout << "输入无效,请输入包含0-8的9位不重复数字。" << endl;
        }
    } while (!isValidInput(start));
    
    int steps = bfs(start, target);
    cout  << steps <     
    return 0;
}

你可能感兴趣的:(算法,广度优先搜索(BFS),方向数组)