题意:题意很好懂的,看下图就知道了,就是连成一块的可以有八种相等的情况,给你一个0 1矩阵,让你将可以通过旋转相等的图形用相同字符表示,不同图形用不同字符表示。
然后,这道题我感觉相当考验编程基础,本身并没有什么算法,顶多就一个DFS或是BFS,我是用DFS写的。
思路:分三步
①找出图中所以联通的1,即两个for遍历矩阵,如果是1,就找出这一块
②每找到一块,就与之前的所有进行比较,如果之前存在相同的,就用之前的那个字符, 如果不存在相同的,就用一个新的字符。
③将这个字符给这一块赋值
最后就是输出
这只是我最开始构思的一个框架,其中有太多的细节了。最典型的就是,你怎么能将当前找到一块和之前的图形进行相比? ----我的做法是直接暴力比,但是,暴力也是不那么容易写的好吧,我也不是纯暴力的。
首先,对于每一小块,我加了元素,即长,宽以及它的字符,很好理解吧,就是一块的一些基本元素。
那么只有长宽都相等的块,才有可能进一步相等。所以我开了一个非常复杂的二维结构体数组,由长度宽度作为下标,里面的内容是相应长度宽度下的块。
每次比较就在这个二维数组中找。
这道题可能写出来后要花很长时间找bug,所以大家还是细心找一下,多编几组测试数据(不要看一组数据那么多0,1觉得不好编,其实还是挺好搞的,就找一个图形,把它八个相等的情况列出来),我的bug都是靠自己的测试数据找出来的。
然后,这个题很可能让你花半天或者一天,但是我觉得都是值得的,能够锻炼找bug的能力。
代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
using namespace std;
int row,col;
queue<int> q;
char s[104][104];
int visit[105][105];
int d1[]={-1,1,0,0,-1,-1,1,1},
d2[]={0,0,-1,1,-1,1,-1,1};
int r1,c1,r2,c2;
struct spe
{
char ch;
char s[105][105];
};
struct spe2
{
vector<spe> v;
};
spe2 p[104][104];
char ch = 'a',previ;
void dfs(int r,int c,char ch)
{
q.push(r);
q.push(c);
s[r][c] = ch;
visit[r][c] = 1;
int rr,cc;
r1 = min(r1,r);
c1 = min(c1,c);
r2 = max(r2,r);
c2 = max(c2,c);
for( int i = 0 ; i < 8 ; i++ )
{
rr = r+d1[i];
cc = c+d2[i];
if( visit[rr][cc] == 0 && s[rr][cc] == '1' )
dfs(rr,cc,ch);
}
}
bool judge( int h,int w )
{
char ss[104][104];
for( int i = r1 ; i <= r2 ; i++ )
for( int j = c1 ; j <= c2 ; j++ )
ss[i][j] = '0';
int x,y;
while( !q.empty() )
{
x = q.front(); q.pop();
y = q.front(); q.pop();
ss[x][y] = '1';
}
spe temp;
temp.ch = ch;
if( h <= w )
{
for( int i = 1 ,rr = r1; i <= h ; i++,rr++ )
{
for( int j = 1,cc = c1 ; j <= w ; j++,cc++ )
temp.s[i][j] = ss[rr][cc];
temp.s[i][w+1] ='\0';
}
}
else
{
swap(h,w);
for( int i = 1,cc = c1 ; i <= h ; i++,cc++ )
{
for( int j = 1,rr = r1 ; j <= w ; j++,rr++ )
temp.s[i][j] = ss[rr][cc];
temp.s[i][w+1] = '\0';
}
}
if( p[h][w].v.size() == 0 )
{
if( h == w )
{
spe temp2;
for( int i = 1 ; i <= h ; i++ )
for( int j = 1 ; j <= w ; j++ )
temp2.s[i][j] = temp.s[j][i];
temp2.ch = temp.ch;
p[h][w].v.push_back(temp2);
}
p[h][w].v.push_back(temp);
return true;
}
int len = p[h][w].v.size();
for( int k = 0 ; k < len ; k++ )
{
previ = p[h][w].v[k].ch;
bool flag = true;
for( int i = 1 ; i <= h ; i++ )
for( int j = 1 ; j <= w ; j++ )
if( temp.s[i][j] != p[h][w].v[k].s[i][j] )
{
flag = false;
goto first;
}
first:
if( flag )
return false;
flag = true;
for( int i = 1,rr = h ; i <= h ; i++,rr-- )
for( int j = 1,cc = 1 ; j <= w ; j++,cc++ )
if( temp.s[rr][cc] != p[h][w].v[k].s[i][j] )
{
flag = false;
goto two;
}
two:
if( flag )
return false;
flag = true;
for( int i = 1,rr = 1 ; i <= h ; i++,rr++ )
for( int j = 1,cc = w ; j <= w ; j++,cc-- )
if( temp.s[rr][cc] != p[h][w].v[k].s[i][j] )
{
flag = false;
goto three;
}
three:
if( flag )
return false;
flag = true;
for( int i = 1,rr = h ; i <= h ; i++,rr-- )
for( int j = 1,cc = w ; j <= w ; j++,cc-- )
if( temp.s[rr][cc] != p[h][w].v[k].s[i][j] )
{
flag = false;
goto four;
}
four:
if( flag )
return false;
}
if( h == w )
{
spe temp2;
for( int i = 1 ; i <= h ; i++ )
for( int j = 1 ; j <= w ; j++ )
temp2.s[i][j] = temp.s[j][i];
temp2.ch = temp.ch;
p[h][w].v.push_back(temp2);
}
p[h][w].v.push_back(temp);
return true; //不与之前的重复
}
int main()
{
memset(visit,0,sizeof visit);
scanf("%d %d",&col,&row);
for( int i = 1 ; i <= row ; i++ )
scanf("%s",s[i]+1);
for( int i = 1 ; i <= row ; i++ )
for( int j = 1 ; j <= col ; j++ )
if( s[i][j] == '1' && visit[i][j] == 0 )
{
r1 = r2 = i,c1 = c2 = j;
dfs(i,j,'1');
int h = r2-r1+1,w = c2-c1+1;
if( judge(h,w) )
s[i][j] = ch++;
else s[i][j] = previ;
}
memset(visit,0,sizeof visit);
for( int i = 1 ; i <= row ; i++ )
for( int j = 1 ; j <= col ; j++ )
if( s[i][j] != '0' )
dfs(i,j,s[i][j]);
for( int i = 1 ; i <= row ; i++ )
printf("%s\n",s[i]+1);
return 0;
}
/*
5 7
10000
10000
11100
00000
10100
10000
11100
*/