蓝桥杯 方格分割(第八届第四题)

标题:方格分割
6x6的方格,沿着格子的边线剪开成两部分。 要求这两部分的形状完全相同。
如图:p1.png, p2.png, p3.png 就是可行的分割法。
p1 p2 p3

试计算: 包括这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.csdn.net/qq_27601815/article/details/70821248

posted @ 2019-03-09 21:28  开局一把刀  阅读(8)  评论(0)    收藏  举报