题目描述
输入描述
输出描述
输入样例1
11 16
################
#....#++++#+...#
#....#++.+#+...#
#....#.++.#++.+#
#....#....#++++#
################
#....#.+..#++++#
#..++#.+..#++.+#
#+...#....#.++.#
#+...#..++#....#
################
输出样例1
4
输入样例2
9 21
#####################
#...+#++++#+...#..+.#
#..+.#.++.#.+..#..+.#
#.+..#....#..+.#..+.#
#####################
#.+..#....#..+.#.+..#
#..+.#.++.#.+..#.+..#
#...+#++++#+...#.+..#
#####################
输出样例2
4
题目大意: 给定一个以字符串描绘的窗户集,每个窗户的形状和大小都相等,且各个窗户之间以 # 隔开,求该窗户集中共有几类不同的窗户(若窗户经过旋转后图案相等,则认为是同一种窗户,不考虑翻转情况)。
初看觉得是 acwing 1402 星空之夜的类似题,然而 acwing 上的做法是求某图形各点的距离以判断两个图形是否相等,且考虑翻转情况并尺寸不固定(泪);
但本题胜在数据范围小,且每个窗户的尺寸固定,因此可以考虑暴力模拟出每扇窗户的四种旋转情况(虽然当窗户的长宽不等时仅存在两种情况,但已经懒得多判断了 )并借助 set 计数,仅有当四种旋转形态都未出现过时,才将该窗户记为新种类。
而存入 set 时,考虑将二维的窗户直接压成一维字符串方便操作。
注意窗户的旋转和每个角度压缩成一维字符串时的长宽条件及转化公式。
参考代码
#include <bits/stdc++.h>
using namespace std;
int ans=0,len=0,wid=0;
const int N=120;
set <string> window;
char g[N][N];//原始
char window1[N][N],window2[N][N],window3[N][N],window4[N][N]; //旋转后窗户
string tostring1(){
string s="";
for(int i=0;i<len;i++)
for(int j=0;j<wid;j++)
s+=window1[i][j];
return s;
}
string tostring2(){
string s="";
for(int i=0;i<wid;i++)
for(int j=0;j<len;j++)
s+=window2[i][j];
return s;
}
string tostring3(){
string s="";
for(int i=0;i<len;i++)
for(int j=0;j<wid;j++)
s+=window3[i][j];
return s;
}
string tostring4(){
string s="";
for(int i=0;i<wid;i++)
for(int j=0;j<len;j++)
s+=window4[i][j];
return s;
}
void zhuan90(){
memset(window2,0,sizeof window2);
for(int i=0;i<wid;i++)
for(int j=0;j<len;j++)
window2[i][j]=window1[len-j-1][i];
}
void zhuan180(){
memset(window3,0,sizeof window3);
for(int i=0;i<len;i++)
for(int j=0;j<wid;j++)
window3[i][j]=window2[wid-j-1][i];
}
void zhuan270(){
memset(window4,0,sizeof window4);
for(int i=0;i<wid;i++)
for(int j=0;j<len;j++)
window4[i][j]=window3[len-j-1][i];
}
//void save(){
//
//}
void judge(){
if(window.empty()){
window.insert(tostring1());
ans++;
return ;
}
string ans1=tostring1();
if(window.find(ans1)!=window.end())
return ;
zhuan90();
string ans2=tostring2();
if(window.find(ans2)!=window.end())
return ;
zhuan180();
string ans3=tostring3();
if(window.find(ans3)!=window.end())
return ;
zhuan270();
string ans4=tostring4();
if(window.find(ans4)!=window.end())
return ;
window.insert(ans1);
ans++;
}
int main(){
int r,c;
cin>>r>>c;
for(int i=0;i<r;i++)
cin>>g[i];
for(int i=1;i<r;i++){
if(g[i][1]!='#')
++len;//垂直
else
break;
}
for(int j=1;j<c;j++){
if(g[1][j]!='#')
++wid;//平行
else
break;
}
int x=1,y=1,mx=r-len-1,my=c-wid-1;
int xx,yy;
for(x=1;x<r;x+=len+1){
for(y=1;y<c;y+=wid+1){
memset(window1,0,sizeof window1);
xx=x+len;yy=y+wid;
for(int i=x;i<xx;i++)//将该窗户分出
for(int j=y;j<yy;j++)
window1[i-x][j-y]=g[i][j];
judge();
}
}
cout<<ans<<endl;
return 0;
}