百练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、挑战,找出踩方格的推导公式