hiho #1474 拆字游戏(dfs,记录状态)

#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 }
 
原文地址:https://www.cnblogs.com/SeekHit/p/6511673.html