题解 P1451 【求细胞数量】
这题一看到应该就可以反应过来是搜连通块的题
搜法分为dfs和bfs
先看样例发现是一串数字所以无法写以下代码
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
那该怎么办
//用字符呗
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
char c;
cin>>c;
a[i][j]=c-'0';
}
或者
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]);//%1d表示只读一位
输入完那就开始搜索吧
先讲bfs
bfs通常会用到队列
这里我推荐一个stl的双向队列,叫做deque
/*
队列基本操作:
deque<int> q;创建一个数双端队列q,int也可以是别的类型
q.empty();判断队列是否为空,为空返回true
q.push_front(s);将s从队头入队
q.push_back(s);将s从队尾入队,和普通队列方式一样
q.front();只返回队头元素
q.back();只返回队尾元素
q.pop_front();将队头元素弹出
q.pop_back;将队尾元素弹出
q.clear();将队列清空
*/
bfs是一层一层搜的 框架如下
//bfs模板
struct ed
{
.....
}
deque<ed>q;
void bfs()
{
标记起点
起点入队列
while(!q.empty())//队列不为空
{
ed nw=q.front();//返回队首
for(拓展出接下来可能的状态)
{
ed nxt;
记录这一状态
判断状态是否合法
标记状态
q.push_back(nxt);//状态入队列
}
q.pop_front();//弹出队首
}
}
所以这题bfs写法如下
#include<bits/stdc++.h>
using namespace std;
struct pp
{
int x,y;
};
deque<pp> q;//队列
int n,m,ans=0;//n行m列,ans为答案
int a[105][105];//存矩阵
bool used[105][105];//记录是否走过
int dx[4]={-1,1,0,0};//向上下左右走一步行号和列好的改变
int dy[4]={0,0,-1,1};
void bfs(int sx,int sy)//bfs
{
pp st;
st.x=sx;st.y=sy;
used[sx][sy]=1;
q.push_back(st);
while(!q.empty())
{
pp nw=q.front();
for(int i=0;i<4;i++)
{
pp nxt=nw;
nxt.x+=dx[i];
nxt.y+=dy[i];
if(a[nxt.x][nxt.y]==0 || used[nxt.x][nxt.y]==1) continue;
used[nxt.x][nxt.y]=1;//把这一连通块的点染色
q.push_back(nxt);
}
q.pop_front();
}
}
int main()
{
cin>>n>>m;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(used[i][j]==0 && a[i][j]!=0)
{
bfs(i,j);
ans++;//若这一连通块没搜过ans++
}
}
}
cout<<ans;
return 0;
}
那dfs呢 dfs是一次走到底,然后回溯
/*
void dfs()
{
for(拓展状态)
{
判断合法
记录
dfs(继续搜);
回溯;
}
}
*/
所以这题dfs代码
#include<bits/stdc++.h>
using namespace std;
int n,m,ans=0;
int a[105][105];
bool used[105][105];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
void dfs(int x,int y)
{
used[x][y]=1;
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(a[nx][ny]==0 || used[nx][ny]==1) continue;
dfs(nx,ny);
}
}
int main()
{
cin>>n>>m;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(used[i][j]==0 && a[i][j]!=0)
{
dfs(i,j);
ans++;
}
}
}
cout<<ans;
return 0;
}
拜拜