八数码 (C++)

本文探讨了在一个二维图中,通过'x'字符的顺时针旋转寻找从起始状态到目标状态的最短路径问题。使用了广度优先搜索(BFS)算法作为基础解法,并对比了其与A*搜索算法的适用性和效率。A*算法虽更高效但可能导致超时,因优先级队列排序成本过高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接
在这里插入图片描述
在这里插入图片描述

分析:

x每移动一次就对应一个状态,这个状态,对应的就是二维图平面中的一个。然后,题目又提到了最短,那么显然,可以采用BFS(最简单的办法,当然A*更好)。

解答(BFS)

#include <iostream>
#include <queue>
#include <unordered_map>
#include <string>

using namespace std;

int main() {
    string des = "12345678x"; // 目标状态
    string start; // 起始状态
    int dx[] = {-1, 0, 1, 0}; // 顺时针旋转
    int dy[] = {0, 1, 0, -1};
    for (int i = 0; i < 9; i++) { // 输入字符串
        char c;
        cin >> c;
        start += c;
    }
    queue<string> q; // 实现BFS的队列
    q.push(start); // 其实状态入队
    unordered_map<string, int> mp; // 存储到达某个状态的最短步数
    mp[start] = 0; // 起点的步数为 0
    while (!q.empty()) {
        string s = q.front(); // 队首元素
        q.pop(); // 将其弹出
        int dis = mp[s]; // 此状态的”步数”
        if (s == des) { // 是否已经到达终点
            cout << dis;
            return 0;
        }
        int idx = s.find('x'); // 找到’x’对应下标
        int x = idx / 3; // 对应‘x’的 x坐标
        int y = idx % 3; // 对应‘x’的 y坐标
        for (int i = 0; i < 4; i++) {
            int next_x = x + dx[i];
            int next_y = y + dy[i];
            swap(s[idx], s[next_x * 3 + next_y]); // 得到下一个“状态”
            if (next_x < 0 || next_x > 2 || next_y < 0 || next_y > 2 ) {
            	// 越界 或者 已经有最短路径了
     			continue;
     		}
     		if (!mp.count(s)) { // 如果是第一次到达这个状态, 即最短步数
            	mp[s] = dis + 1; // 记录到达这个状态的最短步数
           		q.push(s); // 此状态 入队
            }
            swap(s[idx], s[next_x * 3 + next_y]); // 还原
        }
    }
    cout << -1; // 没找到结果
    return 0;
}

解答(A*):

这个时候,就要祭出我们的A*,就是用小顶堆(priority_queue),每次从中选一个最可能的状态———一个确定当前状态到目标状态距离,以及已经走过步数,的评估函数。

不要用这个办法,会超时,可能是priority_queue的排序消耗的时间比算法优化的时间更多,最后会超时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值