当前位置: 首页 > news >正文

《P1379 八数码难题》

题目描述

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

输入格式

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

输出格式

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

输入输出样例

输入 #1复制

283104765

输出 #1复制

4

说明/提示

样例解释

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

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

代码实现:

#include <iostream>
#include <queue>
#include <map>
#include <string>
#include <algorithm>
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<int, int> 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<string> q;
    map<string, int> dist;
    
    q.push(start);
    dist[start] = 0;
    
    while (!q.empty()) {
        string current = q.front();
        q.pop();
        
        pair<int, int> 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 <<endl;
    
    return 0;
}

相关文章:

  • 编程日志5.28
  • w笔记--表格组件(Table)的sorter属性
  • 基于 STM32 的智慧农业温室控制系统设计与实现
  • 如何通过仿真软件优化丝杆升降机设计
  • `sysctl`命令深度剖析:如何优化内核参数以提升服务器网络/IO性能?
  • app获取相册权限是否意味着所有相片都可随时读取?
  • 力扣HOT100之回溯:131. 分割回文串
  • MySQL 只知道表名不知道具体库?如何查询?information_schema入手
  • 深入解析 Flink 中的时间与窗口机制
  • webpack CDN打包优化
  • js 实现多并发任务处理
  • 8Manage PM、Trello与飞书对比评测:哪款项目管理软件更适合企业使用?
  • DAY07:Vue Router深度解析与多页面博客系统实战
  • 数据库 1.0.2
  • Cmake编译yaml-cpp并在QT中测试成功操作步骤
  • 共现矩阵的SVD降维与低维词向量计算详解
  • 【免费】【无需登录/关注】多点矩阵计算器,计算任何坐标系转换
  • Teigha应用——解析CAD文件(DWG格式)Teigha在CAD C#二次开发中的基本应用
  • 2025-05-27 Python深度学习6——神经网络模型
  • C语言_文件操作
  • 高端网站建设公司有哪些/推广关键词排名查询
  • 联通物联网服务运营平台/seo外链工具下载
  • mysql做网站/全世界足球排名国家
  • 百度做网站吗/百度分公司
  • 美女做羞羞的网站/关键词挖掘
  • 制作一个公司网站用vs怎么做/营销手机都有什么功能啊