BestCoder 度度熊的01世界 (DFS)

来源:互联网 发布:百度云域名注册 编辑:程序博客网 时间:2024/06/09 14:51
度度熊的01世界
 
 Accepts: 967
 
 Submissions: 3064
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 32768/32768 K (Java/Others)

Problem Description

度度熊是一个喜欢计算机的孩子,在计算机的世界中,所有事物实际上都只由0和1组成。

现在给你一个n*m的图像,你需要分辨他究竟是0,还是1,或者两者均不是。

图像0的定义:存在1字符且1字符只能是由一个连通块组成,存在且仅存在一个由0字符组成的连通块完全被1所包围。

图像1的定义:存在1字符且1字符只能是由一个连通块组成,不存在任何0字符组成的连通块被1所完全包围。

连通的含义是,只要连续两个方块有公共边,就看做是连通。

完全包围的意思是,该连通块不与边界相接触。

Input

本题包含若干组测试数据。 每组测试数据包含: 第一行两个整数n,m表示图像的长与宽。 接下来n行m列将会是只有01组成的字符画。

满足1<=n,m<=100

Output

如果这个图是1的话,输出1;如果是0的话,输出0,都不是输出-1。

Sample Input
32 32000000000000000000000000000000000000000000011111111000000000000000000000001111111111100000000000000000000011111111111100000000000000000001111111111111100000000000000000011111100011111000000000000000001111100000011110000000000000000011111000000111110000000000000000111110000000111110000000000000011111100000001111100000000000000111111000000001111100000000000001111110000000001111000000000000011111100000000011111000000000000111110000000000111100000000000001111000000000001111000000000000011110000000000011110000000000000111100000000000011100000000000000111100000000000111000000000000001111000000000001110000000000000011110000000000011100000000000001111000000000011110000000000000011110000000000111100000000000000011100000000001111000000000000000111110000011111110000000000000001111100011111111000000000000000011111111111111100000000000000000011111111111111000000000000000001111111111111000000000000000000001111111111100000000000000000000001111111000000000000000000000000011111000000000000000000000000000000000000000000000000032 3200000000000000000000000000000000000000000000000011111100000000000000000000000000111111100000000000000000000000011111111000000000000000000000001111111110000000000000000000000001111111100000000000000000000000011111111000000000000000000000001111111100000000000000000000000011111110000000000000000000000001111111100000000000000000000000011111111100000000000000000000000111111111000000000000000000000001111111100000000000000000000000111111100000000000000000000001111111111000000000000000000001111111111111000000000000000000111111111111110000000000000000001111111111111100000000000000000011111111111110000000000000000000000011111111110000000000000000000000000011111100000000000000000000000001111111000000000000000000000001111111100000000000000000000000001111111100000000000000000000000011111111000000000000000000000000111111111000000000000000000000001111111110000000000000000000000000111111110000000000000000000000000011111111110000000000000000000000111111111100000000000000000000000111111111000000000000000000000000000000000000003 3101101011
Sample Output
01-1

题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=775&pid=1006

解题思路:用DFS找连通块。

                  1、先找到1的连通块,作好标记。如果没有1的连通块或者1的连通块个数大于1,输出“-1”,否则进入第2步。

                  2、找0的连通块,0的连通块有两类,一类是被包围的,一类是不被包围的。如果被包围的0连通块个数为0,输出“1”,个数为1,输出“0”,个数大于1输出”-1“。


代码如下:

#include <cstdio>#include <cstring>#include <iostream>#include <string>using namespace std;int a[105][105];int dx[4] = {0,-1,0,1};  //枚举上下左右四个方向int dy[4] = {1,0,-1,0};string s[105];bool flag1,flag2;int n,m;void dfs_only1(int x,int y){     //找1的连通块a[x][y] = 2;                 //标记找过的1的连通块,赋值为2for(int i = 0; i < 4; i ++){int xx = x + dx[i];       //找下一个点int yy = y + dy[i];if(xx < 0 || yy < 0 || xx >= n || yy >= m || a[xx][yy] == 0 || a[xx][yy] == 2)continue;         //如果下一个点超过边界或者值不为1,则返回找另一个方向的点else dfs_only1(xx,yy);   //如果下一个点满足条件就进入下一层循环}return;}void dfs_only0(int x,int y){     //找0连通块a[x][y] = 3;                 //找过的0连通块值标记为3for(int i = 0; i < 4; i ++){int xx = x + dx[i];int yy = y + dy[i];if(xx < 0 || yy < 0 || xx >= n || yy >= m){flag2 = false;       //flag2标记连通块类型,如果走到边界说明当前0连通块是不被包围的continue;}if(a[xx][yy] == 3 || a[xx][yy] == 2)continue;dfs_only0(xx,yy);}return;}int main(){while(scanf("%d%d",&n,&m)!=EOF){flag1 = true;int x1 = -1,y1 = -1;        //找第一个值为1的点的下标int x0 = -1,y0 = -1;        //找第一个值为0的点的下标memset(a,0,sizeof(a));for(int i = 0;i < n; i ++){cin >> s[i];for(int j = 0;j < m; j++){a[i][j] = s[i][j] - '0';if(a[i][j] == 1 && x1 == -1){x1 = i;y1 = j;}if(x0 == -1 && y0 == -1 && a[i][j] == 0){x0 = i;y0 = j;}}}if(x1 == -1 || y1 == -1){        //没有1连通块输出“-1”printf("-1\n");continue;}dfs_only1(x1,y1);for(int i = 0 ; i < n; i++){for(int j = 0; j < m ;j ++){if(a[i][j] == 1){        //有大于一个1连通块输出“-1”flag1 = false;break;}}if(flag1 == false)break;}if(flag1 == false){printf("-1\n");continue;}int cnt0 = 0;            //标记被包围的0连通块个数for(int i = 0; i < n; i++){for(int j = 0; j < m;j ++){if(a[i][j] == 0){flag2 = true;    //标记0连通块是否被包围,true表示被包围dfs_only0(i,j);if(flag2 == true){cnt0 ++;}if(cnt0 > 1)   break;}}if(cnt0 > 1)break;}if(cnt0 == 1)         //根据被包围的0连通块个数判断图像类型printf("0\n");else if(cnt0 == 0)printf("1\n");elseprintf("-1\n");} return 0;}