华容道问题的dfs实现

#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;

// 定义上下左右移动的偏移量
constexpr static int dx[] = {0, 1, -1, 0};
constexpr static int dy[] = {1, 0, 0, -1};

// 定义行列数
const int row = 3;
const int column = 4;

// 定义目标状态
const int target[row][column] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 0}};

// 存储每个数字的目标位置
unordered_map<int, pair<int, int>> position;

// 计算曼哈顿距离,用于判断状态是否达到目标状态
int manhattan_distance(const vector<vector<int>>& state) {
    int distance = 0;
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j) {
            int num = state[i][j];
            if (num != 0) {
                int target_x = position[num].first;
                int target_y = position[num].second;
                distance += abs(i - target_x) + abs(j - target_y);
            }
        }
    }
    return distance;
}

// 判断当前状态是否为目标状态
bool is_true(const vector<vector<int>>& state) {
    return manhattan_distance(state) == 0;
}

// 深度优先搜索
bool dfs(vector<vector<int>>& state, int x, int y, int mx, int my, int num, vector<vector<int>>& pos) {
    // 边界条件
    if (x < 0 || x >= row || y < 0 || y >= column) return false;
    if (state[x][y] != 0) swap(state[x][y], state[mx][my]); // 交换空白块和相邻块的位置
    if (is_true(state)) return true; // 如果当前状态已经是目标状态,返回true
    if (pos[x][y] == 1) return false; // 如果当前状态已经被访问过,返回false
    if (num == 100000) return false; // 限制搜索深度,避免无限递归
    pos[x][y] = 1; // 标记当前状态已经被访问
    bool flag = false;
    for (int i = 0; i < 4; ++i) { // 对当前状态的四个方向进行搜索
        int tx = x + dx[i];
        int ty = y + dy[i];
        flag = flag || dfs(state, tx, ty, x, y, num + 1, pos); // 递归搜索下一个状态
    }
    pos[x][y] = 0; // 重置访问标记
    swap(state[x][y], state[mx][my]); // 恢复原来的状态
    return flag; // 返回是否找到解
}

// 判断初始状态是否可解
bool solvable(vector<vector<int>>& initial_state) {
    vector<vector<int>> pos(row, vector<int>(column, 0)); // 记录状态是否被访问过
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j) {
            position[initial_state[i][j]] = {i, j}; // 记录每个数字的位置
        }
    }
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j) {
            if (initial_state[i][j] == 0) {
                pos.assign(row, vector<int>(column, 0)); // 重置访问标记
                return dfs(initial_state, i, j, i, j, 0, pos); // 深度优先搜索
            }
        }
    }
    return false;
}


int main(){
    vector<vector<int>> initial_state = {
        {5, 6, 7, 8},
        {0, 1, 2, 3},
        {4, 9, 10, 11}
    };
    cout << (solvable(initial_state) ? "True" : "False") << endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值