宝岛探险--着色法

宝岛探险–着色法

要求

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值