hiho232 拆字游戏

版权声明:转载我的原创博客情注明出处 https://blog.csdn.net/qq_31964727/article/details/85236796

题目1 : 拆字游戏

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Kui喜欢把别人的名字拆开来,比如“螺”就可以拆成“虫田糸”,小Kui的语文学的不是很好,于是她决定使用编程的方式来解决这个问题。

给出一个01矩阵,1占据的部分即为需要拆的字,如果两个1分享一条边,那么它们连通。连通具有传递性,即如果a、b连通,b、c连通,则a、c连通。

连通的一系列1被看做可以拆出的一块,现在小Kui需要输出这些拆出的块(用一个01矩阵表示,并且要求矩阵的大小尽可能的小)。

为了确保输出的顺序尽可能的和书写的顺序一致,小Kui从每个块中选出最左上角的点(最左侧的点中,最靠上的)作为代表点,然后按照代表点从左到右(若相同则按从上到下)的顺序输出所有拆出的块。

输入

输入的第一行为两个正整数N、M,表示01矩阵的大小。

接下来N行,每行M个01字符,描述一个需要拆的字。

对于40%的数据,满足1<=N,M<=10。

对于100%的数据,满足1<=N,M<=500。

输出

按照代表点从左到右(若相同则按从上到下)的顺序输出所有拆出的块。

对于每个块,先输出其大小,然后用对应的01矩阵表示这个块。

额外的样例

样例输入 样例输出
11 17
00000000000000000
00001111111100000
00000000000000000111
001111111111111001
00000000100000000
00000010101110001
00000110100011000
00011100100001000
00000010100000000
00000001100000000
00000000000000000
7 13
1111111111111
0000001000000
0000001000000
0000001000000
0000001000000
0000001000000
0000011000000
3 4
0001
0011
1110
1 8
11111111
1 1
1
3 4
1110
0011
0001

样例输入

14 22
0000000000001111111100
0000000000001101101100
0000110000001111111100
0000110000001101101100
0111111110001111111100
0110110110000000000000
0110110110000011000000
0111111110001111111000
0000110000000001100000
0000110110001111111100
0111111111000111111000
0000000010001101101100
0000000000000001100000
0000000000000011100000

样例输出

10 9
000110000
000110000
111111110
110110110
110110110
111111110
000110000
000110110
111111111
000000010
5 8
11111111
11011011
11111111
11011011
11111111
8 8
00110000
11111110
00011000
11111111
01111110
11011011
00011000
00111000

题意分析:

1.题是什么?

    其实就是给你一个长n宽m的01矩阵,现在要你把这个图中连通的1视作一块拆分输出出来,连通是用的四连通规则.

2.思路

    做一个flag数组把像素图收录进去,然后二重循环依次判断flag[i][j]为1则从此点开始进行bfs,将此点及与此点连通的位置的flag值全部置为0,同时把经过的点记录到vector中,bfs的同时更新出此次dfs中经过的所有点的边界,此次bfs结束后,遍历vector把ans中对应的位置全部更新为1,输出对应边界内的ans,然后再次遍历vector把ans的所有位置更新为0并清空vector.继续寻找下一块

3.细节

    小心对于输入的处理,c语言中读单字符要自己处理换行符,我是用getchar()过滤的,

    其次一定要注意是按最左上方的1为准从左到右从上到下依次输出.

ac代码:

#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
const int maxn=505;
int path[4][2]={1,0,0,-1,-1,0,0,1};//四方向数组 
char image[maxn][maxn];
char flag[maxn][maxn];
char ans[maxn][maxn];

vector<pair<int,int> > black;
int leftedge,rightedge,upedge,downedge;
void bfs(int x,int y,const int& n,const int& m){ //找出所有黑点存入black并更新出边界 
	flag[x][y]='0';
	upedge=downedge=x,leftedge=rightedge=y;
	black.clear();
	black.push_back(make_pair(x,y));
	for(int index=0;index<black.size();index++){
		for(int i=0;i<4;i++){
			int tx=black[index].first+path[i][0],ty=black[index].second+path[i][1];
			if(0<=tx&&tx<n&&0<=ty&&ty<m&&flag[tx][ty]=='1'){
				flag[tx][ty]='0';
				if(tx>downedge) downedge=tx;
				if(tx<upedge) upedge=tx;
				if(ty>rightedge) rightedge=ty;
				if(ty<leftedge) leftedge=ty; 
				black.push_back(make_pair(tx,ty));
			}
		}
	}
}
void solve(){
	int n,m; 
	scanf("%d%d",&n,&m);
	getchar();
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++) scanf("%c",&image[i][j]); 
		getchar();
	}
	
	//初始化,录入image到flag并初始ans画布 
	for(int i=0;i<n;i++) for(int j=0;j<m;j++){
		if(image[i][j]=='0') flag[i][j]='0';
		else if(image[i][j]=='1') flag[i][j]='1';
		ans[i][j]='0';
	}
	for(int j=0;j<m;j++) for(int i=0;i<n;i++){
		if(flag[i][j]=='1'){
			bfs(i,j,n,m);
			//渲染ans画布 
			for(int k=0;k<black.size();k++) ans[black[k].first][black[k].second]='1'; 
			//输出ans画布 
			printf("%d %d\n",downedge-upedge+1,rightedge-leftedge+1);
			for(int k=upedge;k<=downedge;k++){
				for(int l=leftedge;l<=rightedge;l++) printf("%c",ans[k][l]); 
				printf("\n");
			}
			//清空ans画布 
			for(int k=0;k<black.size();k++) ans[black[k].first][black[k].second]='0';
		}
	}
}

int main(){
	solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_31964727/article/details/85236796