深度优先搜索01

百练2815城堡问题

  题目是深搜的入门题目,题目描述很难搬过来,不是图片,可以点上面的题目看描述:
大致意思就是:一个封闭四边形,里面有一些挡板组成封闭空间,我们要找出有多少这样的封闭空间,最大的空间是多大。题目本身的编码方式很值得借鉴:

  用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。
  而这样的编码用二进制写出来就是_ _ _ _,每个位置1代表有墙0代表没墙。可巧妙的使用 与 运算,具体见代码。

那下面我们具体说,深度优先搜索。具体将用到记忆性递归,可以说深搜一般都用到递归了。我们从上到下从左到右进行记忆性递归,假使该节点没有被遍历过,那么将这个节点标记为当前房间的颜色(或者标记),并且对它周围没有标记的点进行搜索,并且每次循环中递归结束之后,记录房间的大小,从中找出最大的一个(稍微有点歧义)。

void DFS(int i, int j) {
    if (color[i][j]) {
        return;
    }
    room_area++;
    color[i][j] = num_room;
    if ((Array[i][j] & 2) == 0) {
        DFS(i - 1, j);
    }
    if ((Array[i][j] & 8) == 0) {
        DFS(i + 1, j);
    }
    if ((Array[i][j] & 1) == 0) {
        DFS(i, j - 1);
    }
    if ((Array[i][j] & 4) == 0) {
        DFS(i, j + 1);
    }
}

想清楚之后还是很简单的。下面看一道很类似的4982:踩方格
想象我们面前有无数个浮空的板子,每个板子踩过之后就不能再被踩,给出移动的步数,要求我们计算出所有可能的路线数。
题目比较容易的地方是,我们容易发现这样的递推关系:

Ways[i, j, n] = Ways[i, j - 1, n -1] + Ways[i, j + 1, n -1] + Ways[i + 1, j, n -1] #没有被踩过的三个点的路径数

我试图用递归来解决,却发现边界条件不太好找,而第三维的步数很容易作为递归的终止条件,所以:

int ways ( int i,int j,int n) {
       if( n == 0)
             return 1;
        visited[i][j] = 1;
        int num = 0;
        if( ! visited[i][j-1] )
             num+= ways(i,j-1,n-1);
        if( ! visited[i][j+1] )
             num+= ways(i,j+1,n-1); 
        if( ! visited[i+1][j] )
             num+= ways(i+1,j,n-1);
        visited[i][j] = 0;//注意这里
        return num;
}

练习题

1、滑雪_百练1088
   !#尝试用动规和记忆性递归两种办法解决
2、用动规解决第二题,踩方格
3、挑战,找出踩方格的推导公式

你可能感兴趣的:(深度优先搜索01)