zoj 2100

       回顾DFS算法的。其实吧,在我看来DFS本质就是个递归(当然对应地自己用栈存储搜索路径的话就可以比避免反复的递归调用),递归抓住两点即可:

       1. 递归的算法,在这里就是确定下一个搜索结点;

       2. 递归结束条件,在这里就是所有节点都访问过或者无路可走则结束;


       另外,做这个题的时候发现了自己以前写代码的一个隐患,我在开字符数组的时候总是不把结束符算进去,总是想当然认为是根据我开的数组的大小对字符串截取后存储的,但实际上是全部顺序存入的。。。一旦覆盖了其他有用数据时就会出问题的,多数时候预留的空间比较大所以一直都没发现这个问题。。        


/*******************************
** 这道题用的深度优先搜索,DFS 核心  **
** 算法利用的是递归,一定要注意递归   **
** 结束条件。这道题算是熟悉一下 DFS  **
** 写的时候在递归结束条件上犯错了,   **
** cout初始值没有周全考虑导致出错。  **
*******************************/
#include<stdio.h>
#define MAX 6
char f[MAX][MAX+1];
int n, m;

int dfs(int l, int r, int count)
{
    f[l][r] = 'S';
    count ++;
    if(count == n*m)
        return 1;

    /* 扫描按照:下,左,右,上的顺序 */
    /* down */
    if(l < n-1 && f[l+1][r] != 'S')
    /* 方案可行则向上返回 */
        if(dfs(l+1, r, count))
            return 1;
    
    /* 函数没有返回表明,此步不合适 */
    /* left */
    if(r > 0 && f[l][r-1] != 'S')
        if(dfs(l, r-1, count))
            return 1;

    /* right */
    if(r < m-1 && f[l][r+1] != 'S')
        if(dfs(l, r+1, count))
            return 1;
    /* up */
    if(l > 0 && f[l-1][r] != 'S')
        if(dfs(l-1, r, count))
            return 1;

    /* 退回一步 */
    f[l][r] = '.';
    count --;
    return 0;
}

int main()
{
    int i, j, count;

    while(scanf("%d%d", &n, &m), m+n)
    {
        count = 0;
        for(i = 0; i < n; i++)
        {
            scanf("%s", f[i]);
            for(j = 0; j < m; j++)
                if(f[i][j] == 'S')
                    count ++;
        }

        if(dfs(0, 0, count))
            printf("YES\n");
        else
            printf("NO\n");
    }
}
/**************************************
** 调试过程中发现一个细节问题,最初数组开的是 **
** f[MAX][MAX],想着刚好能放下字符串就行。  **
** 但调试时发现,虽然自己定义的数组读取的时候 **
** 没有问题,但是实际上内存中存的是字符串本身 **
** 加上 '\0' 结束符号;仔细分析来看,c 中多维数 **
** 组本身就是个一维数组,读入时就是按顺序往里 **
** 存;如果编译器给函数预留的局部变量空间刚好 **
** 够用时,最后读入的 '\0' 会覆盖后面其他变量。 **
** 我在调试的时候就发现,最后总是输入字符串完 **
** 成后,n 的突变为 0。所以说,针对字符数组来 **
** 说,开空间必须是字符串长度加 1 !!!             **
**************************************/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值