PIPIOJ1033拆字游戏:
题目描述:
PiPi喜欢把别人的名字拆开来,比如“螺”就可以拆成“虫田糸”,PiPi的语文学的不是很好,于是她决定使用编程的方式来解决这个问题。
给出一个01矩阵,1占据的部分即为需要拆的字,如果两个1分享一条边,那么它们连通。连通具有传递性,即如果a、b连通,b、c连通,则a、c连通。
连通的一系列1被看做可以拆出的一块,现在PiPi需要输出这些拆出的块(用一个01矩阵表示,并且要求矩阵的大小尽可能的小)。
为了确保输出的顺序尽可能的和书写的顺序一致,PiPi从每个块中选出最左上角的点(最左侧的点中,最靠上的)作为代表点,然后按照代表点从左到右(若相同则按从上到下)的顺序输出所有拆出的块。
输入:
多组数据。
输入的第一行为两个正整数N、M,表示01矩阵的大小。
接下来N行,每行M个01字符,描述一个需要拆的字。
对于40%的数据,满足1<=N,M<=10。
对于100%的数据,满足1<=N,M<=500。
输出:
按照代表点从左到右(若相同则按从上到下)的顺序输出所有拆出的块。
对于每个块,先输出其大小,然后用对应的01矩阵表示这个块。
解答:
实际上就是图的BFS,一道典型的搜索题。需要注意的是,规定了输出的顺序,所以在主函数中,查找还未被访问过的顶点是先列后行的顺序。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=503;
char maze[N][N];//输入的01矩阵
bool vis[N][N];
struct Node{
int row,col;//点的坐标
};
int ans[N][N];
int sx,sy,ans_row,ans_col;
int dir[4][2]={1,0,0,-1,-1,0,0,1};
int n,m;//n行m列
bool check(int x,int y){
if(maze[x][y]=='1'&&x>=0&&x<n&&y>=0&&y<m&&!vis[x][y])
return true;
else
return false;
}
void bfs(int x,int y){//bfs的起点(x,y)
memset(ans,0,sizeof(ans));
queue<Node> q;
q.push({x,y});
vis[x][y]=1;
ans[x][y]=1;
sx=x,sy=y,ans_row=x,ans_col=y;//sx,sy表示能包含当前块的最小矩阵左上角顶点在原图的坐标,ans_row和ans_col表示矩阵底边和右边在原图中的行号、列号
while(q.size()){
Node now=q.front();
q.pop();
for(int i=0;i<4;i++){
Node next;
next.row=now.row+dir[i][0];
next.col=now.col+dir[i][1];
if(check(next.row,next.col)){
q.push(next);
ans[next.row][next.col]=1;
vis[next.row][next.col]=1;
if(sx>next.row)//更新答案矩阵的各项参数
sx=next.row;
if(sy>next.col)
sy=next.col;
if(ans_row<next.row)
ans_row=next.row;
if(ans_col<next.col)
ans_col=next.col;
}
}
}
}
int main(int argc, char** argv) {
memset(vis,0,sizeof(vis));
scanf("%d %d\n",&n,&m);//以防下一个scanf读入换行符,加上\n
for(int i=0;i<n;i++){
scanf("%s",maze[i]);
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(maze[j][i]=='1'&&!vis[j][i]){//如果还有顶点未被访问到
sx=0,sy=0,ans_row=0,ans_col=0;
bfs(j,i);
printf("%d %d\n",ans_row-sx+1,ans_col-sy+1);
for(int p=sx;p<=ans_row;p++){
for(int q=sy;q<=ans_col;q++){
printf("%d",ans[p][q]);
}
printf("\n");
}
}
}
}
return 0;
}
该博客介绍了如何通过BFS算法解决一个与字符矩阵拆分有关的问题。PiPi试图将一个01矩阵中的连通1部分拆分成单独的块,并按特定顺序输出。题目要求从每个块的最左上角开始,按从左到右、从上到下的顺序排列。博主提供了C++代码实现,该代码首先通过BFS遍历找到所有连通块,并更新答案矩阵,然后按照题目要求输出结果。
328

被折叠的 条评论
为什么被折叠?



