《啊哈!算法》-第 4 章:萬能的搜索 - 寶島冒險

寶島冒險

題目

小哼經過祕密方法獲得了一張不完整的釣魚島航拍地圖。釣魚島由一個主島和一些附屬島嶼組成,小哼決定去釣魚島冒險。下面這個 10 * 10 的二維碼矩陣就是釣魚島的航拍地圖。圖中數字表明海拔,0 表示海洋,1~9 表示陸地。小哼的飛機將會在(6,8)處,如今須要計算出小哼落地所在島嶼的面積(即有多少個格子)。node

1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0

計算小島面積

#include <stdio.h>
#define NUM 10

int a[NUM][NUM] = {
  {1, 2, 1, 0, 0, 0, 0, 0, 2, 3},
  {3, 0, 2, 0, 1, 2, 1, 0, 1, 2},
  {4, 0, 1, 0, 1, 2, 3, 2, 0, 1},
  {3, 2, 0, 0, 0, 1, 2, 4, 0, 0},
  {0, 0, 0, 0, 0, 0, 1, 5, 3, 0},
  {0, 1, 2, 1, 0, 1, 5, 4, 3, 0},
  {0, 1, 2, 3, 1, 3, 6, 2, 1, 0},
  {0, 0, 3, 4, 8, 9, 7, 5, 0, 0},
  {0, 0, 0, 3, 7, 8, 6, 0, 1, 2},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
};
int book[NUM][NUM];
int direction[4][2] = {
  {-1, 0},
  {0, 1},
  {1, 0},
  {0, -1}
};

int main(void) {
  int i, j, tx, ty, area = 0;

  for (i = 0; i < NUM; i++)
    for (j = 0; j < NUM; j++)
      book[i][j] = 0;

  // 初始化隊列
  struct node {
    int x;
    int y;
  } que[1000];
  int head = 0;
  int tail = 0;
  // 初始化位置
  que[tail].x = 6;
  que[tail].y = 8;
  tail++;
  book[6][8] = 1;
  area++;

  while (head < tail) {
    for (i = 0; i < 4; i++) {
      tx = que[head].x + direction[i][0];
      ty = que[head].y + direction[i][1];

      if (tx >= 0 && tx < NUM && ty >= 0 && ty < NUM) {
        if (a[tx][ty] > 0 && book[tx][ty] == 0) {
          book[tx][ty] = 1;
          a[tx][ty] = -1;
          que[tail].x = tx;
          que[tail].y = ty;
          tail++;
          area++;
        }
      }
    }
    
    head++;
  }

  printf("%d\n", area);

  for (i = 0; i < NUM; i++) {
    for (j = 0; j < NUM; j++) {
      printf("%2d ", a[i][j]);      
    }
    printf("\n");    
  }

  return 0;
}

用符號表示路過的小島

#include <stdio.h>
#define NUM 10

int a[NUM][NUM] = {
  {1, 2, 1, 0, 0, 0, 0, 0, 2, 3},
  {3, 0, 2, 0, 1, 2, 1, 0, 1, 2},
  {4, 0, 1, 0, 1, 2, 3, 2, 0, 1},
  {3, 2, 0, 0, 0, 1, 2, 4, 0, 0},
  {0, 0, 0, 0, 0, 0, 1, 5, 3, 0},
  {0, 1, 2, 1, 0, 1, 5, 4, 3, 0},
  {0, 1, 2, 3, 1, 3, 6, 2, 1, 0},
  {0, 0, 3, 4, 8, 9, 7, 5, 0, 0},
  {0, 0, 0, 3, 7, 8, 6, 0, 1, 2},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
};
int book[NUM][NUM];
int sum = 0;
int direction[4][2] = {
  {-1, 0},
  {0, 1},
  {1, 0},
  {0, -1}
};

void dfs(int x, int y, int color) {
  int i, tx, ty;
  // 邊界

  a[x][y] = color;

  // 嘗試每一步
  for (i = 0; i < 4; i++) {
    tx = x + direction[i][0];
    ty = y + direction[i][1];

    if (tx >= 0 && tx < NUM && ty >= 0 && ty < NUM) {
      if (a[tx][ty] > 0 && book[tx][ty] == 0) {
        book[tx][ty] = 1;
        sum++;
        // 下一步
        dfs(tx, ty, color);
      }
    }
  }
}

int main(void) {
  int i, j;

  dfs(6, 8, -1);

  printf("%d\n", sum);

  for (i = 0; i < NUM; i++) {
    for (j = 0; j < NUM; j++) {
      printf("%2d ", a[i][j]);      
    }
    printf("\n");    
  }

  return 0;
}

記錄地圖有多少個小島

#include <stdio.h>
#define NUM 10

int a[NUM][NUM] = {
  {1, 2, 1, 0, 0, 0, 0, 0, 2, 3},
  {3, 0, 2, 0, 1, 2, 1, 0, 1, 2},
  {4, 0, 1, 0, 1, 2, 3, 2, 0, 1},
  {3, 2, 0, 0, 0, 1, 2, 4, 0, 0},
  {0, 0, 0, 0, 0, 0, 1, 5, 3, 0},
  {0, 1, 2, 1, 0, 1, 5, 4, 3, 0},
  {0, 1, 2, 3, 1, 3, 6, 2, 1, 0},
  {0, 0, 3, 4, 8, 9, 7, 5, 0, 0},
  {0, 0, 0, 3, 7, 8, 6, 0, 1, 2},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
};
int book[NUM][NUM];
int direction[4][2] = {
  {-1, 0},
  {0, 1},
  {1, 0},
  {0, -1}
};

void dfs(int x, int y, int color) {
  int i, tx, ty;
  // 邊界

  a[x][y] = color;

  // 嘗試每一步
  for (i = 0; i < 4; i++) {
    tx = x + direction[i][0];
    ty = y + direction[i][1];

    if (tx >= 0 && tx < NUM && ty >= 0 && ty < NUM) {
      printf("%d %d\n", tx, ty);
      if (a[tx][ty] > 0 && book[tx][ty] == 0) {
        book[tx][ty] = 1;
        // 下一步
        dfs(tx, ty, color);
      }
    }
  }
}

int main(void) {
  int i, j, num = 0;

  for (i = 0; i < NUM; i++) {
    for (j = 0; j < NUM; j++) {
      if (a[i][j] > 0 && book[i][j] == 0) {
        num--;
        book[i][j] = 1;
        dfs(i, j, num);
      }
    }
  }

  // dfs(0, 0, -1);

  for (i = 0; i < NUM; i++) {
    for (j = 0; j < NUM; j++) {
      printf("%2d ", a[i][j]);      
    }
    printf("\n");    
  }

  printf("%d\n", -num);

  return 0;
}

這一個算法就是鼎鼎大名的 FloodFill 漫水填充法(也稱種子填充法)。經常使用於圖像分割、物體識別等等。算法

相關文章
相關標籤/搜索