城堡问题

非递归实现本质就是手工模拟系统栈的操作,这里使用stack与pair进行模拟。需要注意的是,传统的递归转非递归,需要将子问题逆向地加入栈。在《城堡问题》中,这并不是必要的,原因是四个方向的搜索顺序并不影响最终的结果。

以下是城堡问题 - DFS递归实现的非递归实现:

#include <cstdio>
#include <algorithm>
#include <stack>
#include <utility>

using namespace std;

const int DIR = 4;
const int dx[] = { 0, -1, 0, 1 };
const int dy[] = { -1, 0, 1, 0 };
const int masks[] = { 1, 2, 4, 8 };

int m, n;
int g[51][51];
int f[51][51] = { 0 };

bool inRange(int x, int y) {
  return x >= 0 && x < m && y >= 0 && y < n;
}

int dfs(int x, int y) {
  stack<pair<int, int> > s;
  s.push(make_pair(x, y));
  int sum = 0;
  while (!s.empty()) {
    pair<int, int> top = s.top();
    s.pop();
    x = top.first, y = top.second;
    if (f[x][y] > 0) continue;
    f[x][y] = 1;
    sum++;
    for (int i = 0; i < DIR; i++) {
      int xx = x + dx[i], yy = y + dy[i];
      if (!inRange(xx, yy)) continue;
      if ((g[x][y] & masks[i]) != 0) continue;
      if ((g[xx][yy] & masks[(i + 2) % DIR]) != 0) continue;
      s.push(make_pair(xx, yy));
    }
  }
  return sum;
}

int main() {
  int i, j;
  scanf("%d%d", &m, &n);
  for (i = 0; i < m; i++)
    for (j = 0; j < n; j++)
      scanf("%d", &g[i][j]);

  int roomNum = 0, maxArea = 0;
  for (i = 0; i < m; i++) {
    for (j = 0; j < n; j++) {
      if (f[i][j] == 0) {
        maxArea = max(maxArea, dfs(i, j));
        roomNum++;
      }
    }
  }
  printf("%d\n%d\n", roomNum, maxArea);

  return 0;
}

Recursive

自己手敲了一下递归实现,与视频不同的地方有:

使用了一个数组记录方向与位运算的mask
增加边界判断,视频中貌似没有进行边界判断,不知道是否存在下标越界问题
使dfs函数直接返回值而没有用全局变量记录
代码如下:

#include <cstdio>
#include <algorithm>

using namespace std;

const int DIR = 4;
const int dx[] = { 0, -1, 0, 1 };
const int dy[] = { -1, 0, 1, 0 };
const int masks[] = { 1, 2, 4, 8 };

int m, n;
int g[51][51];
int f[51][51] = { 0 };

bool inRange(int x, int y) {
  return x >= 0 && x < m && y >= 0 && y < n;
}

int dfs(int x, int y) {
  if (f[x][y] > 0)
    return 0;

  f[x][y] = 1;
  int sum = 1;
  for (int i = 0; i < DIR; i++) {
    int xx = x + dx[i], yy = y + dy[i];
    if (!inRange(xx, yy)) continue;
    if ((g[x][y] & masks[i]) != 0) continue;
    if ((g[xx][yy] & masks[(i + 2) % DIR]) != 0) continue;
    sum += dfs(xx, yy);
  }
  return sum;
}

int main() {
  int i, j;
  scanf("%d%d", &m, &n);
  for (i = 0; i < m; i++)
    for (j = 0; j < n; j++)
      scanf("%d", &g[i][j]);

  int roomNum = 0, maxArea = 0;
  for (i = 0; i < m; i++) {
    for (j = 0; j < n; j++) {
      if (f[i][j] == 0) {
        maxArea = max(maxArea, dfs(i, j));
        roomNum++;
      }
    }
  }
  printf("%d\n%d\n", roomNum, maxArea);

  return 0;
}

results matching ""

    No results matching ""