#1474 : 拆字游戏
时间限制: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 00000000000000000 00111111111111100 00000000100000000 00000010101110000 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
思路:
本质上是一个深搜的题,不过需要记录深搜的状态,将搜到所有的非联通路径记录下来。
因为是按列的顺序,所以搜的时候优先列方向遍历。
AC代码:
1 // 2 // Created by SeeKHit on 2017/3/5. 3 // 4 5 #include "iostream" 6 #include "vector" 7 #include "algorithm" 8 #define MAX 505 9 using namespace std; 10 11 char a[MAX][MAX]; 12 int di[4]={1,-1,0,0}; 13 int dj[4]={0,0,1,-1}; 14 int n,m; 15 int n1=0; //记录多少个块 16 17 vector<pair<int,int>> vv[500*505];//记录图形点的数组 18 19 void dfs(int i,int j,int id) 20 { 21 a[i][j]='x'; 22 vv[id].push_back(make_pair(i-1,j-1)); 23 int ar=1; 24 for(int ii=0;ii<4;ii++) 25 { 26 int ni=di[ii]+i,nj=dj[ii]+j; 27 if(a[ni][nj]=='1') 28 dfs(ni,nj,id); 29 } 30 } 31 32 int vvv[500][505]; //记录字块 33 void Print(int id) 34 { 35 int cow=0,rol=0; 36 int maxx=0,minx=1e9,maxy=0,miny=1e9; 37 for(int t=0;t<vv[id].size();t++) 38 { 39 maxx=max(maxx,vv[id][t].first); 40 minx=min(minx,vv[id][t].first); 41 maxy=max(maxy,vv[id][t].second); 42 miny=min(miny,vv[id][t].second); 43 44 int x=vv[id][t].first; 45 int y=vv[id][t].second; 46 47 } 48 rol=maxy-miny+1; 49 cow=maxx-minx+1; 50 cout<<cow<<" "<<rol<<endl; 51 52 for(int t=0;t<vv[id].size();t++) 53 { 54 int x=vv[id][t].first; 55 int y=vv[id][t].second; 56 57 vvv[x-minx][y-miny]=1; 58 59 } 60 61 for(int i=0;i<cow;i++) 62 { 63 for(int j=0;j<rol;j++) 64 { 65 cout<<vvv[i][j]; 66 vvv[i][j]=0; 67 68 } 69 cout<<endl; 70 } 71 } 72 73 int main() 74 { 75 scanf("%d %d",&n,&m); 76 for(int i=0;i<n;i++) 77 scanf("%s",a[i+1]+1); 78 79 80 for(int j=1;j<=m;j++) 81 for(int i=1;i<=n;i++) 82 { 83 if(a[i][j]=='1') 84 { 85 n1++; 86 dfs(i,j,n1); 87 } 88 } 89 90 for(int i=1;i<=n1;i++) 91 { 92 Print(i); 93 } 94 }