蓝桥杯刷题——方格分割(深度优先搜索)

282 阅读2分钟

「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」。

这道题的难度定义为中等难度,是一道深度优先搜索的题目。如果知道正确运用深度优先搜索来解,这道题是不难的,只是如何想到去用,这里是一个难点。

题目

给定一个6x6的方格,沿格子线进行切割,最后结果要求切割出的两部分完全相同。 要求求出一共有多少种不同的切割方法。

旋转对称属于同一种切法。

image.png

如图,这是一个切法。

思路

要切出一模一样的部分,我们应该怎么去切?我们可以想象有一根连续的线,这根线是可以上下左右移动的,然后有另一根一样的线,从一个起点开始,这根线往上走,另一根线就往下走,始终走与这根线相反的方向。这一根线走到边界时,另一根线也走到了边界。这个时候,整个方格就被分成了两部分。这个时候,这两部分一定是一样的。知道如何去分割,接下来我们就可以设计程序了。设一个二维数组,6x6的方格一共有36个点,我们从最中间的点(3,3),开始,往上下左右四个方向开始走,还有另一根线往相反的方向切割。到达边界时我们就可以将切割的方法加一了。但是这样得到的总切割方法数不是正确的,往上下左右四个方向走,跟另一个方向的走法会有一次重复,所以我们需要将结果除以2,但是旋转对称是属于同一种切法的,我们还需要将结果除以2。加起来就是一共除以4得到最终答案。

代码

#include<bits/stdc++.h>
using namespace std;
int vis[7][7];//算上边界一共49个点
int turn[4][2]={0,1,0,-1,1,0,-1,0};//模拟四个方向
int ans;
void dfs(int x,int y){
    if(x==0||y==0||x==6||y==6){
        ans++;
        return;
    }
    int x1,y1,x2,y2;
    for(int i=0;i<4;i++){
        x1=x+turn[i][0];
        y1=y+turn[i][1];
        x2=6-x1;
        y2=6-y1;
        if(!vis[x1][y1]){
            vis[x1][y1] = vis[x2][y2] = 1;
            dfs(x1,y1);
            vis[x1][y1] = vis[x2][y2] = 0;
        }
    }
    
}
int main(){
    memset(vis, 0, sizeof(vis));
    vis[3][3] = 1;
    dfs(3,3);
    cout<<ans/4;
    return 0;
}