《啊哈算法》第四章 万能的搜索之着色法

来源:互联网 发布:做网络销售工资怎么样 编辑:程序博客网 时间:2024/04/30 04:38

参考:《啊哈算法》

背景:宝岛探险。

用一个10*10的二维矩阵表示某岛的的航拍地图,用数字表示海拔,0表示海洋,1-9表示陆地,给出一个下降点,求出该点所在陆地小岛的面积。

解决方案1:从给出点开始进行bfs,边界设为值大于0,真是好办
bfs展示

#include <cstdio>#define N 100int maps[N][N];int book[N][N];int next[4][2]= {{0,1},{1,0},{0,-1},{-1,0}};typedef struct Que {    int x;    int y;};int main() {    Que que[1001];    int a,b,startx,starty;    scanf("%d%d%d%d",&a,&b,&startx,&starty);    for(int i=0; i<a; i++) {        for(int j=0; j<b; j++) {            scanf("%d",&maps[i][j]);        }    }    int head=1;    int tail=1;    book[startx][starty]=1;    que[head].x=startx;    que[head].y=starty;    tail++;    while(head<tail) {//操作简直是简单多了,        int tx,ty;        for(int i=0; i<=3; i++) {            tx=que[head].x+next[i][0];            ty=que[head].y+next[i][1];            if(tx<1||tx>=a||ty<1||ty>=b) {                continue;            }            if(maps[tx][ty]>0&&book[tx][ty]==0) {//这个边界好呀                book[tx][ty]=1;                que[tail].x=tx;                que[tail].y=ty;                tail++;            }        }        head++;    }    printf("%d\n",head-1);    return 0;}

dfs展示

#include <cstdio>#define N 100int maps[N][N];int book[N][N];int a,b,startx,starty;int next[4][2]= {{0,1},{1,0},{0,-1},{-1,0}};int sum=0;void dfs(int x,int y) {    int tx,ty;    sum++;    for(int i=0; i<=3; i++) {        tx=x+next[i][0];        ty=y+next[i][1];        if(tx<0||tx>=a||ty<0||ty>=b) {            continue;        }        if(maps[tx][ty]>0&&book[tx][ty]==0) {            book[tx][ty]=1;            dfs(tx,ty);//为什么这里不用回收,因为我们是搜索符合条件的点不是尝试到目的地        }    }}int main() {    scanf("%d%d%d%d",&a,&b,&startx,&starty);    for(int i=0; i<a; i++) {        for(int j=0; j<b; j++) {            scanf("%d",&maps[i][j]);        }    }    book[startx][starty]=1;    dfs(startx,starty);    printf("%d\n",sum);    return 0;}

同一个测试:

 10 10 6 8//一个10*10的矩阵地图中,降落在第六行第八列求该点所在岛屿面积1 2 1 0 0 0 0 0 2 33 0 2 0 1 2 1 0 1 24 0 1 0 1 2 3 2 0 13 2 0 0 0 1 2 4 0 00 0 0 0 0 0 1 5 3 00 1 2 1 0 1 5 4 3 00 1 2 3 1 3 6 2 1 00 0 3 4 8 9 7 5 0 0 0 0 0 3 7 8 6 0 1 20 0 0 0 0 0 0 0 1 0

简单直白的着色,,,,,就是在dfs或bfs时改变一下原二维数组的值,进行统一

#include <cstdio>#define N 100int maps[N][N];int book[N][N];int a,b,startx,starty;int next[4][2]= {{0,1},{1,0},{0,-1},{-1,0}};int sum=0;void dfs(int x,int y) {    int tx,ty;    maps[x][y]=-1;    for(int i=0; i<=3; i++) {        tx=x+next[i][0];        ty=y+next[i][1];        if(tx<0||tx>=a||ty<0||ty>=b) {            continue;        }        if(maps[tx][ty]>0&&book[tx][ty]==0) {            book[tx][ty]=1;            dfs(tx,ty);//为什么这里不用回收,因为我们是搜索符合条件的点不是尝试到目的地        }    }}int main() {    scanf("%d%d%d%d",&a,&b,&startx,&starty);    for(int i=0; i<a; i++) {        for(int j=0; j<b; j++) {            scanf("%d",&maps[i][j]);        }    }    book[startx][starty]=1;    dfs(startx,starty);    printf("\n");    for(int i=0; i<a; i++) {        for(int j=0; j<b; j++) {            printf("%3d",maps[i][j]);        }        printf("\n");    }    // printf("%d\n",sum);    return 0;}

测试:

10 10 6 81 2 1 0 0 0 0 0 2 33 0 2 0 1 2 1 0 1 24 0 1 0 1 2 3 2 0 13 2 0 0 0 1 2 4 0 00 0 0 0 0 0 1 5 3 00 1 2 1 0 1 5 4 3 00 1 2 3 1 3 6 2 1 00 0 3 4 8 9 7 5 0 0 0 0 0 3 7 8 6 0 1 20 0 0 0 0 0 0 0 1 0

控制台情况

那么问题来了,怎么知道地图中有多少个独立的小岛屿?

解决方案:每一个非零点都要进行遍历,一直枚举到二维数组最后一个元素(当然是从头到尾)不指定起始地址

dfs展示
注意我们存放时全是大于0的数,着色时尽量使用负数,以免重复,。,。,我是犯了错误的

#include <cstdio>#define N 100int maps[N][N];int book[N][N];int a,b,startx,starty;int next[4][2]= {{0,1},{1,0},{0,-1},{-1,0}};int sum=-1;//这里有点诡异void dfs(int x,int y,int color) {    int tx,ty;    maps[x][y]=color;    for(int i=0; i<=3; i++) {        tx=x+next[i][0];        ty=y+next[i][1];        if(tx<0||tx>=a||ty<0||ty>=b) {            continue;        }        if(maps[tx][ty]>0&&book[tx][ty]==0) {            book[tx][ty]=1;            dfs(tx,ty,color);//为什么这里不用回收,因为我们是搜索符合条件的点不是尝试到目的地        }    }}int main() {    scanf("%d%d",&a,&b);    for(int i=0; i<a; i++) {        for(int j=0; j<b; j++) {            scanf("%d",&maps[i][j]);        }    }    for(int i=0; i<a; i++) {        for(int j=0; j<b; j++) {            if(maps[i][j]>0) {                {                    book[i][j]=1;                    dfs(i,j,sum);                    sum--;                }            }        }    }    printf("\n");    for(int i=0; i<a; i++) {        for(int j=0; j<b; j++) {            printf("%3d",maps[i][j]);        }        printf("\n");    }    // printf("%d\n",sum);    return 0;}

测试:

10 10 1 2 1 0 0 0 0 0 2 33 0 2 0 1 2 1 0 1 24 0 1 0 1 2 3 2 0 13 2 0 0 0 1 2 4 0 00 0 0 0 0 0 1 5 3 00 1 2 1 0 1 5 4 3 00 1 2 3 1 3 6 2 1 00 0 3 4 8 9 7 5 0 0 0 0 0 3 7 8 6 0 1 20 0 0 0 0 0 0 0 1 0

控制台

原来这就是求一个图中独立子图的个数,Floodfill漫水填充法(也称种子填充法)

0 0