宝岛探险--着色法

时间:2022-09-16 06:38:42

宝岛探险–着色法

要求

0代表海洋,1~9代表陆地,飞机降落在(5, 7)处,开始探索,统计探索的面积(格子数)。

思路

从(5, 7)处开始广度优先搜索,被加入队列的点的总数就是小岛面积。

bfs代码

#include <stdio.h>

#define N 10
#define M 10

int a[N][M] = {
{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 b[N][M] = {0};

struct node
{
int x;
int y;
};

struct node que[401]; // 地图大小不超过20*20
int head = 0, tail = 0;

void enqueue(struct node p) {
que[tail] = p;
tail++;
}

struct node dequeue() {
head++;
return que[head-1];
}

int is_empty() {
return head == tail;
}

void print_a() {
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
printf("\n");
}

void print_b() {
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
printf("%d ", b[i][j]);
}
printf("\n");
}
printf("\n");
}

int main() {

int sum = 0;
struct node p = {5, 7};
enqueue(p);
b[p.x][p.y] = 1;
sum++;

while(!is_empty()) {
p = dequeue();

// bfs 搜索可以探险的点
if (a[p.x][p.y+1] != 0 && b[p.x][p.y+1] == 0 && p.y+1 < M) {
struct node temp = {p.x, p.y+1};
enqueue(temp);
b[p.x][p.y+1] = 1;
sum++;
}

if (a[p.x+1][p.y] != 0 && b[p.x+1][p.y] == 0 && p.x+1 < N) {
struct node temp = {p.x+1, p.y};
enqueue(temp);
b[p.x+1][p.y] = 1;
sum++;
}

if (a[p.x][p.y-1] != 0 && b[p.x][p.y-1] == 0 && p.y-1 >= 0) {
struct node temp = {p.x, p.y-1};
enqueue(temp);
b[p.x][p.y-1] = 1;
sum++;
}

if (a[p.x-1][p.y] != 0 && b[p.x-1][p.y] == 0 && p.x-1 >= 0) {
struct node temp = {p.x-1, p.y};
enqueue(temp);
b[p.x-1][p.y] = 1;
sum++;
}

}

print_a();
print_b();
printf("sum: %d\n", sum);
return 0;
}

思路

也可以使用深度优先搜索,下面使用递归的方式实现深度优先搜索。

dfs代码

#include <stdio.h>

#define N 10
#define M 10

int a[N][M] = {
{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 b[N][M] = {0};
int sum = 0;

struct node
{
int x;
int y;
};

void print_a() {
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
printf("\n");
}

void print_b() {
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
printf("%d ", b[i][j]);
}
printf("\n");
}
printf("\n");
}

void dfs(struct node p) {

if (a[p.x][p.y+1] != 0 && b[p.x][p. y+1] == 0 && p.y+1 < M) {
b[p.x][p.y+1] = 1;
sum++;
struct node temp = {p.x, p.y+1};
dfs(temp);
}

if (a[p.x+1][p.y] != 0 && b[p.x+1][p.y] == 0 && p.x+1 < N) {
b[p.x+1][p.y] = 1;
sum++;
struct node temp = {p.x+1, p.y};
dfs(temp);
}

if (a[p.x][p.y-1] != 0 && b[p.x][p.y-1] == 0 && p.y-1 >= 0) {
b[p.x][p.y-1] = 1;
sum++;
struct node temp = {p.x, p.y-1};
dfs(temp);
}

if (a[p.x-1][p.y] != 0 && b[p.x-1][p.y] == 0 && p.x-1 >= 0) {
b[p.x-1][p.y] = 1;
sum++;
struct node temp = {p.x-1, p.y};
dfs(temp);
}
}

int main() {

struct node p = {5, 7};
dfs(p);

print_a();
print_b();
printf("sum: %d\n", sum);
return 0;
}

总结

以上方法叫做着色法,以某个点为源点对其邻近的点进行着色。应用场景有:ps的魔术棒工具。

扩展–漫水填充法

求地图中又多少个独立的小岛?(求一个图中独立子图的个数)

思路

枚举法对地图上每一个大于0的点进行一遍深度优先搜索。

代码

#include <stdio.h>

#define N 10
#define M 10

int a[N][M] = {
{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 b[N][M] = {0};
int sum = 0;

struct node
{
int x;
int y;
};

void print_a() {
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
printf("%3d ", a[i][j]);
}
printf("\n");
}
printf("\n");
}

void print_b() {
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
printf("%3d ", b[i][j]);
}
printf("\n");
}
printf("\n");
}

void dfs(struct node p, int color) {

a[p.x][p.y] = color;

if (a[p.x][p.y+1] != 0 && b[p.x][p. y+1] == 0 && p.y+1 < M) {
b[p.x][p.y+1] = 1;
sum++;
struct node temp = {p.x, p.y+1};
dfs(temp, color);
}

if (a[p.x+1][p.y] != 0 && b[p.x+1][p.y] == 0 && p.x+1 < N) {
b[p.x+1][p.y] = 1;
sum++;
struct node temp = {p.x+1, p.y};
dfs(temp, color);
}

if (a[p.x][p.y-1] != 0 && b[p.x][p.y-1] == 0 && p.y-1 >= 0) {
b[p.x][p.y-1] = 1;
sum++;
struct node temp = {p.x, p.y-1};
dfs(temp, color);
}

if (a[p.x-1][p.y] != 0 && b[p.x-1][p.y] == 0 && p.x-1 >= 0) {
b[p.x-1][p.y] = 1;
sum++;
struct node temp = {p.x-1, p.y};
dfs(temp, color);
}
}

int main() {
int i, j;
int num = -1;
for (i = 0; i < N; ++i) {
for (j = 0; j < M; ++j) {
if (a[i][j] > 0){
struct node p = {i, j};
dfs(p, num--);
}
}
}

print_a();
print_b();
printf("sum: %d\n", sum);
return 0;
}