标题:方格分割
6x6的方格,沿着格子的边线剪开成两部分。 要求这两部分的形状完全相同。
如图:p1.png, p2.png, p3.png 就是可行的分割法。
![]()
![]()
试计算: 包括这3种分法在内,一共有多少种不同的分割方法。 注意:旋转对称的属于同一种分割法。
请提交该整数,不要填写任何多余的内容或说明文字。
第一次做的时候有点不理解中心对称,查了一下
中心对称是指把一个图形绕着某一点旋转180°,如果它能够与另一个图形重合,那么就说这两个图形关于这个点对称或中心对称(central symmetry)。
开始的思路是用dfs搜索小方格的个数搜到18就停止,仔细分析后发现行不通,因为有时候有18个小格子,两个格子并不相等。而且终止条件也不对,万一没搜到边界就满足18终止了,怎么办。于是调整思路,分割线将图形分成完全相同,于是猜想这两个图形肯定是中心对称的,这个分割线也是,看了一下示例发现还真是,这下就简单了,从(3,3)开始两条线往边界走,由于旋转对称的属于同一种分割法。所以往四周走是一样的,我们可以只往一个方向走。我们就往最下面走,row==0&&col>0&&col<6
为终止条件,写出代码,
#include <iostream>
using namespace std;
int vis[7][7];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int cnt;
void dfs(int row,int col){
if(row==0&&col>0&&col<6){
cnt++;
return;
}
if(row<=0||row>=6||col<=0||col>=6||vis[row][col])return;
vis[row][col]=1;
vis[6-row][6-col]=1;
for(int i=0;i<4;i++)dfs(row+dir[i][0],col+dir[i][1]);
vis[row][col]=0;
vis[6-row][6-col]=0;
}
int main(){
dfs(3,3);
cout<<cnt;
}
上面这份代码不太优雅,为了只到一遍需要一些不太直观的条件,参考网友的博客,最终为下面这样,从中心出发,只要到达边界结果就加1,总结果除以4即所得。
#include <iostream>
using namespace std;
int vis[7][7];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int cnt;
void dfs(int row,int col){
if(row==0||row==6||col==0||col==6){
cnt++;
return;
}
if(row<0||row>6||col<0||col>6||vis[row][col])return;
vis[row][col]=1;
vis[6-row][6-col]=1;
for(int i=0;i<4;i++)dfs(row+dir[i][0],col+dir[i][1]);
vis[row][col]=0;
vis[6-row][6-col]=0;
}
int main(){
dfs(3,3);
cout<<cnt/4;
}
参考:
https://baike.baidu.com/item/中心对称
https://blog.youkuaiyun.com/qq_27601815/article/details/70821248