输入一个n*n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数。如果两个黑格子有公共边或者公共顶点,就说它们属于同一个八连块。如图6-11所示的图形有3个八连块。

图6-11  拥有3个八连块的黑白图形

【分析】

用递归求解:从每个黑格子出发,递归访问它所有的相邻黑格。

int mat[MAXN][MAXN], vis[MAXN][MAXN];
void dfs(int x, int y) {
if(!mat[x][y] || vis[x][y]) return; // 曾经访问过这个格子,或者当前格子是白色
vis[x][y] = 1; // 标记(x,y)已访问过
dfs(x-1,y-1); dfs(x-1,y); dfs(x-1,y+1);
dfs(x-1,y); dfs(x,y+1);
dfs(x+1,y-1); dfs(x+1,y); dfs(x+1,y+1); // 递归访问周围的八个格子
}
这里,黑格(x,y)的mat[x][y]为1,白格为0。为了避免同一个格子访问多次,用标志vis[x][y]记录格子(x,y)是否访问过。在输入之前,在迷宫的外面加上一圈虚拟的白格子,见下面的程序。
memset(mat, 0, sizeof(mat)); //所有格子都初始化为白色,包括周围一圈的虚拟格子
memset(vis, 0, sizeof(vis)); // 所有格子都没有访问过
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%s", s);
for(int j = 0; j < n; j++)
mat[i+1][j+1] = s[j]-'0'; // 把图像往中间移动一点,空出一圈白格子
}

接下来,只需不断找黑格,然后调用dfs。从它出发寻找八连块:

int count = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(!vis[i][j] && mat[i][j]) { count++; dfs(i,j); }
//找到没有访问过的黑格
printf("%d\n", count);

完整的程序如下:

#include <stdio.h>
#include <string.h>
const int MAXN = 1000;
int n; int mat[MAXN][MAXN], vis[MAXN][MAXN];
void dfs(int x, int y) { if(!mat[x][y] || vis[x][y]) return; //曾经访问过这个格子,或者当前
格子是白色
vis[x][y] = 1; // 标记(x,y)已访问过
dfs(x-1,y-1); dfs(x-1,y); dfs(x-1,y+1);
dfs(x-1,y); dfs(x,y+1);
dfs(x+1,y-1); dfs(x+1,y); dfs(x+1,y+1); // 递归访问周围的八个格子
} int main() {
char s[MAXN + 10];
memset(mat, 0, sizeof(mat)); // 所有格子都初始化为白色,包括周围
一圈的虚拟格子
memset(vis, 0, sizeof(vis)); // 所有格子都没有访问过
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%s", s);
for(int j = 0; j < n; j++)
mat[i+1][j+1] = s[j]-'0'; // 把图像往中间移动一点,空出一圈白格子
}
int count = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
// 找到没有访问过的黑格
if(!vis[i][j] && mat[i][j]) { count++; dfs(i,j); }
printf("%d\n", count);
return 0;
}

上面的函数dfs就是深度优先遍历(Depth-FirstSearch,DFS)的算法,DFS和BFS一样,都是从一个结点出发,按照某种特定的次序访问图中的其他特点。不同的是,BFS使用队列来存放待扩展结点,而DFS使用的是栈。

附:我自己理解后敲的代码:

#include <stdio.h>
#include <string.h>
#include<algorithm>
#include<iostream>
#define M 1020
using namespace std;
int n;
int i,j;
char map[M][M];
void dfs(int x,int y)
{ if(map[x][y]!='1'||x<0||y<0||x>=n||y>=n)
return; //曾经访问过这个格子,或者当前格子是白色
else
{
map[x][y] = '0'; // 标记(x,y)已访问过
dfs(x-1,y-1);
dfs(x-1,y+1);
dfs(x-1,y);
dfs(x,y+1);
dfs(x,y-1);
dfs(x+1,y-1);
dfs(x+1,y);
dfs(x+1,y+1); // 递归访问周围的八个格子
}
} int main()
{
memset(map, 0, sizeof(map)); // 所有格子都没有访问过
scanf("%d", &n);
for(i=0; i<n; i++)
for(j=0; j<n; j++)
cin>>map[i][j]; int count = 0;
for(i = 0; i <n; i++)
for(j = 0; j <n; j++)
{
// 找到没有访问过的黑格
if(map[i][j]=='1')
{
dfs(i,j);
count++;
}
}
printf("%d\n", count);
return 0;
}
/*
6
100100
001010
000000
110000
111000
010100
*/

黑白图像(DFS)的更多相关文章

  1. dfs入门-cogs1640[黑白图像]

    题目链接:http://cogs.pro:8081/cogs/problem/problem.php?pid=vxSmxkeqa [题目描述] 输入一个n×n的黑白图像(1表示黑色,0表示白色),任务 ...

  2. 小白书 黑白图像【DFS/Flood Fill】

    http://blog.csdn.net/u010470972/article/details/33415617 Description 输入一个n×n的黑白图像(1表示黑色,0表示白色),任务是统计 ...

  3. [ActionScript 3.0] AS3.0 将图像的Alpha通道转换为黑白图像(分离ARGB方式)

    import flash.display.BitmapData; import flash.display.Bitmap; /** * 将图像的Alpha通道转换为黑白图像(分离ARGB方式) */ ...

  4. [ActionScript 3.0] AS3.0将图像的Alpha通道转换为黑白图像(复制通道方式)

    import flash.display.BitmapData; /** * 将图像的Alpha通道转换为黑白图像 */ var p:Point = new Point(0,0); var bmpd: ...

  5. TZOJ 3533 黑白图像(广搜)

    描述 输入一个n*n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数.如果两个黑格子有公共边或者公共顶点,就说它们属于同一个八连块.如图所示的图形有3个八连块. 输入 第1行输入一个正 ...

  6. MATLAB读取黑白图像显示却是黑色,24位深转8位深黑白图像解决方法

    1.24位深转8位深: ps将24位深原图.png保存为GIF图256即为8位,再将8位gif图转为需要的.png,即转为8位深png图. 2.MATLAB读取黑白图像显示几乎全为黑色: 这是最近处理 ...

  7. uoj #139. 【UER #4】被删除的黑白树 dfs序 贪心

    #139. [UER #4]被删除的黑白树 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/139 Descript ...

  8. uva806 Spatial Structures 空间结构 (黑白图像的四分树表示)

    input 8 00000000 00000000 00001111 00001111 00011111 00111111 00111100 00111000 -8 9 14 17 22 23 44 ...

  9. Visio中如何绘制黑白图像

随机推荐

  1. YII session存储 调用login方法

    当要进行用户的session存储的时候,可以调用里面的login方法进行存储

  2. Cobar介绍及配置

    from:http://code.alibabatech.com/wiki/display/cobar/Home Skip to end of metadata   Page restrictions ...

  3. TatukGIS - GisDefs - CreateMSJET 函数

    函数名称  CreateMSJET 所在单元  GisDefs 函数原型           function CreateMSJET(const _path: String): String;   ...

  4. 得到某个进程所有线程ID和入口地址

    #include <windows.h> #include <tlhelp32.h> #include "iostream" using namespace ...

  5. Markdown 测试

    量化派业务参考代码 测试二级标题 如果 merchant_id 是外部白条,则执行相关逻辑 if(order.getMerchantId() == Constants.BaitiaoMerchant. ...

  6. JSP的优势与劣势浅析

    本文简单介绍了JSP技术,并对JSP的优势与劣势进行了简单的分析.JSP页面由HTML代码和嵌入其中的Java代码所组成. JSP(JavaServer Pages)是由Sun Microsystem ...

  7. Plan-9效应:为什么东西不坏就不要去修它

    http://www.aqee.net/the-plan-9-effect-or-why-you-should-not-fix-it-if-it-aint-broken/ Plan-9是一个很棒的.很 ...

  8. SVN简明使用方法 .

    SVN简明使用方法 TortoiseSVN 是 Subversion 版本控制系统的一个免费开源客户端,可以超越时间的管理文件和目录.文件保存在中央版本库,除了能记住文件和目录的每次修改以外,版本库非 ...

  9. cf D George and Interesting Graph

    题意:给你一个有趣图的定义:在这个图中有一个根,根与每个点都有边和回边,除了根之外,其他的点的出度和入度都为2,然后给你一个图让你经过几步操作可以使此图变为有趣图,操作为:删边或者加边. 思路:枚举根 ...

  10. CN消息的来源——父窗口不知道怎么处理,于是把这个消息加上CN_BASE在分发到实际的子窗体

    VCL存在一些非API消息以供其内部使用,为什么要这样做呢?这要从WM_COMMAND & WM_NOTIFY消息说起,我们说WM_COMMAND消息并不是直接发给实际产生消息的窗体,而是发送 ...