【东华oj】5.回形取数

文章讨论了使用深度优先搜索(DFS)解决矩阵遍历问题时遇到的挑战,包括递归实现的弊端(可能引发爆栈)和if判断规则的理解。作者通过示例代码解释了DFS的实现细节,如避免数组越界和优化判断顺序。当数据量过大时,为避免爆栈,文章提到了转换为循环逻辑的必要性,并展示了相应的循环解决方案。
摘要由CSDN通过智能技术生成

首先学习了一下别人的代码,用的深优,确实自己好久不接触这一部分代码了,导致自己根本没想递归的那一方面,dfs的方式可能有些弊端,但是代码相对来讲更容易实现一些。

另外就是if的判断规则,以前这边有点模糊,有点印象,但是不太确定,这次试验了一下,果然是从左向右依次判断。—— 在 "||" 条件下,发现一个满足即可走if里,后面的条件不再判断;

#include <iostream>
#include<iomanip>
#include<math.h>
using namespace std;

void dfs(int **a,int m,int n,int al,int bl) {
    
    if (m < 0 || n < 0 || m >= al || n >= bl || a[m][n] == -1) {  
        //这里a[m][n]要放在最后,
        //学到了,放在前面的话就有可能数组越界的错误
        //(if的判断顺序)
        return;
    }
    if (m == 0 && n == 0)cout << a[m][n];
    else cout << " " << a[m][n];
    a[m][n] = -1;
    dfs(a, m + 1, n, al, bl);
    dfs(a, m, n + 1, al, bl);
    dfs(a, m - 1, n, al, bl);
    dfs(a, m, n - 1, al, bl);
}

int main() {
    int a, b;
    while (cin >> a >> b) {
        int** array = new int* [a];
        for (int i = 0; i < a; i++) {
            array[i] = new int [b];
        }
        for (int i = 0; i < a; i++) {
            for (int j = 0; j < b; j++) {
                cin >> array[i][j];
            }
        }
        dfs(array, 0, 0, a, b);
        cout << endl;
    }
    return 0;
}

但是用这种方式ac不了,可能是数据量过大,导致爆栈。所以只能细分逻辑去写循环了。

#include <iostream>
#include<iomanip>
#include<math.h>
using namespace std;
int main() {
    int m, n;
    while (cin >> m >> n) {
        int** a = new int* [m];
        for (int i = 0; i < m; i++) {
            a[i] = new int[n];
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                cin >> a[i][j];
            }
        }
        int i = 1, j = 0;
        int num = m * n - 1;
        cout << a[0][0];  // DHU的oj风格 最后一个元素后没有空格
        while (num) {
            //cout << i << "  " << j << endl;
            int flag = 1;
            //往下走
            for (; i < m; i++) {
                //cout << "下" << endl;
                if (a[i][j] != -1) {
                    cout << " " << a[i][j];
                    a[i][j] = -1;
                    num--;
                }
                else {
                    i--;
                    flag = 0;
                    break;
                }
            }
            if (num == 0)break;
                //右转准备
            if (flag == 1)i--;
            if (j < n - 1) j++;
            flag = 1;
            //往右走
            for (; j < n; j++) {
                if (a[i][j] != -1) {
                    cout << " " << a[i][j];
                    a[i][j] = -1;
                    num--;
                }
                else {
                    j--;
                    flag = 0;
                    break;
                }
            }
            if (num == 0)break;
                //上转准备
            if (flag == 1)j--;
            if (i > 0 && i < m)i--;

            //往上走
            flag = 1;
            for (; i >= 0 && i < m; i--) {
                if (a[i][j] != -1) {
                    cout << " " << a[i][j];
                    a[i][j] = -1;
                    num--;
                }
                else {
                    i++;
                    flag = 0;
                    break;
                }
            }
            if (num==0)break;
            if (flag == 1)i++;
            if (j > 0) j--;

            flag = 1;
            for (; j > 0; j--) {
                if (a[i][j] != -1) {
                    cout << " " << a[i][j];
                    a[i][j] = -1;
                    num--;
                }
                else {
                    j++;
                    flag = 0;
                    break;
                }
            }
            if (num == 0)break;
                //下一次下转准备
            if (flag == 1) j++;
            if (i < m - 1)i++;
        }
        cout << endl;
    }
    return 0;
}

一开始在写的时候判断逻辑偷懒了,每个if的条件写的不够全面,所以到后面调试的时候只好在每次转向之前先判断是否break(跳出整体循环)才AC掉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值