度度熊的01世界
Accepts: 967
Submissions: 3064
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
题目链接: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的连通块,赋值为2
for(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连通块值标记为3
for(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");
else
printf("-1\n");
}
return 0;
}