You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++处理3×3矩阵排列时出现Segmentation Fault问题排查

问题分析与解决方案

你遇到的Segmentation Fault主要有两个核心原因:递归DFS导致的栈溢出,以及全局状态缓存未清空引发的内存耗尽,再加上算法本身不适合寻找最短路径,导致效率极低且资源占用过大。

具体错误原因

  • 递归深度超限:DFS递归会沿着一条路径不断深入,对于3×3矩阵的状态空间,最坏情况下递归深度可能达到数万级别,而程序的栈空间通常只有几MB,最终触发栈溢出(SIGSEGV)。
  • 全局map未清空:你的mp是全局变量,即使单个测试用例,递归过程中也会不断向其中添加状态,随着状态数累积(最多可达9! = 362880个),内存占用持续增长,最终malloc分配内存失败。
  • 算法选型不当:DFS并不适合寻找最短路径(最小步数),它会优先探索深层路径,不仅效率低,还无法保证第一次找到的是最优解,需要额外维护min_count,进一步增加了资源消耗。

修正方案:改用BFS算法

BFS(广度优先搜索)是寻找最短路径的标准算法,它按层级遍历状态,第一次到达目标状态时的步数就是最小步数,而且用迭代方式实现,不会有栈溢出问题。同时我们可以优化状态表示,用整数代替字符串,减少内存占用和状态转换时间。

以下是修正后的代码:

#include <bits/stdc++.h>
using namespace std;

// 判断是否为质数(题目中两数之和最大为9+8=17,所以只需判断到17)
bool isPrime(int n) {
    return n == 2 || n == 3 || n == 5 || n == 7 || n == 11 || n == 13 || n == 17;
}

// 将3x3矩阵转换为整数(比如123456789)
int matrixToInt(const vector<vector<int>>& mat) {
    int num = 0;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            num = num * 10 + mat[i][j];
        }
    }
    return num;
}

// 将整数转换回3x3矩阵
void intToMatrix(int num, vector<vector<int>>& mat) {
    for (int i = 2; i >= 0; --i) {
        for (int j = 2; j >= 0; --j) {
            mat[i][j] = num % 10;
            num /= 10;
        }
    }
}

void solve() {
    vector<vector<int>> vec(3, vector<int>(3));
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            cin >> vec[i][j];
        }
    }

    const int target = 123456789;
    int start = matrixToInt(vec);
    if (start == target) {
        cout << 0 << endl;
        return;
    }

    // BFS队列:存储当前状态和对应的步数
    queue<pair<int, int>> q;
    // 记录已访问的状态,避免重复处理
    unordered_set<int> visited;

    q.push({start, 0});
    visited.insert(start);

    // 四个方向:右、下(对应原代码中的交换相邻元素)
    vector<pair<int, int>> dirs = {{0, 1}, {1, 0}};

    int min_count = -1;
    while (!q.empty()) {
        auto [current_num, steps] = q.front();
        q.pop();

        vector<vector<int>> mat(3, vector<int>(3));
        intToMatrix(current_num, mat);

        // 遍历所有位置,尝试交换相邻元素
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                for (auto [di, dj] : dirs) {
                    int ni = i + di;
                    int nj = j + dj;
                    if (ni >= 0 && ni < 3 && nj >=0 && nj <3) {
                        // 检查两数之和是否为质数
                        if (isPrime(mat[i][j] + mat[ni][nj])) {
                            swap(mat[i][j], mat[ni][nj]);
                            int next_num = matrixToInt(mat);
                            if (next_num == target) {
                                min_count = steps + 1;
                                // 找到答案后直接退出所有循环
                                goto end_search;
                            }
                            if (!visited.count(next_num)) {
                                visited.insert(next_num);
                                q.push({next_num, steps + 1});
                            }
                            // 交换回来,恢复原矩阵
                            swap(mat[i][j], mat[ni][nj]);
                        }
                    }
                }
            }
        }
    }

end_search:
    cout << min_count << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int test;
    cin >> test;
    while (test--) {
        solve();
    }
    return 0;
}

关键优化点

  • 状态表示优化:用整数代替字符串,将3x3矩阵转换为一个9位数,比字符串更节省内存,且哈希和比较操作更快。
  • BFS迭代实现:使用队列代替递归,避免栈溢出问题,且第一次到达目标状态时的步数就是最小步数,无需维护min_count变量。
  • 局部化状态缓存:将visited设为solve()的局部变量,每次测试用例后自动销毁,不会积累状态导致内存泄漏。
  • 输入输出优化:添加ios::sync_with_stdio(false); cin.tie(nullptr);加速输入输出,避免因大量IO导致的性能问题。

测试你提供的输入用例:

1
7 3 2
4 1 5
6 8 9

程序会正确输出6,且不会触发Segmentation Fault。

内容的提问来源于stack exchange,提问作者Sourabh Khandelwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 08:52:45