参考资料
练习题 icon lost
交流讨论
笔记
img lost

标题:方格分割

6x6的方格,沿着格子的边线剪开成两部分。
要求这两部分的形状完全相同。

如图:p1.png, p2.png, p3.png 就是可行的分割法。

试计算:
包括这3种分法在内,一共有多少种不同的分割方法。
注意:旋转对称的属于同一种分割法。

请提交该整数,不要填写任何多余的内容或说明文字。

p1.png

由于图像是中心对称,所以我们穷举左边的18个方格,共有2^18=262144种可能的情况,穷举出左边,通过对称再得到右边18个方格的情况,从而得到整附图:

 for(int i=0;i < (1<<18);++i)   //i=0~2^18-1
    {
        for(int l=0;l<6;l++)
        {
            for(int c=0;c < 3;c++)
            {
                if(i&(1<<cnt))   //把i的每一位取出填入图形
                {
                    mp[l][c] = 1;     //填充左半部分  1代表橘色  0代表黄色
                    mp[5-l][5-c] = 0;  //对称得到右半部分
                }else
                {
                    mp[l][c] = 0;   
                    mp[5-l][5-c] = 1;
                }
            
            }
        }

然后对填充后的图形进行连通性检测,如果填充后的图形存在18个方块的连通域则符合要求,方案数加一,用DFS检测连通:

int vis[6][6];
int dx[8]={1, 0, 0,-1};
int dy[8]={0,-1, 1, 0};
int node_cnt;

int dfs(int x, int y)
{
    
    for(int i=0;i < 4;i++)     //从当前方格的上,下,左,右进行搜索
    {
        int nx = x + dx[i];   
        int ny = y + dy[i];
        if(node_cnt==18) return node_cnt;   //已找到18个连通的方块,则进行剪枝
        if(0<=nx && nx < 6 && 0<=ny && ny <6)
        {
            if(mp[nx][ny]==mp[x][y]&&vis[nx][ny]==0)  //找到同一区域方块
            {
                vis[nx][ny]=1;   //,标记
                node_cnt++;    //方块数加1
                dfs(nx,ny);
            }
        }
    }
    
    
    return node_cnt;

以下是完整代码:

#include <iostream>
#include <cstring>
using namespace std;

int mp[6][6];
int vis[6][6];
int dx[8]={1, 0, 0,-1};
int dy[8]={0,-1, 1, 0};
int node_cnt;

void printmp()
{
	for(int i=0; i < 6;i++)
	{
		for(int j=0 ;j < 6;j++)
		{
			cout<<mp[i][j]<<" ";
		}
		cout<<endl;
	}
}


int dfs(int x, int y)
{
	
	for(int i=0;i < 4;i++)
	{
		int nx = x + dx[i];
		int ny = y + dy[i];
		if(node_cnt==18) return node_cnt;
		if(0<=nx && nx < 6 && 0<=ny && ny <6)
		{
			if(mp[nx][ny]==mp[x][y]&&vis[nx][ny]==0)
			{
				vis[nx][ny]=1;
				node_cnt++;	
				dfs(nx,ny);
			}
		}
	}
	
	
	return node_cnt;
} 

int main()
{
    int ans=0;
	for(int i=0;i < (1<<18);++i)
	{
		int cnt=0;
		for(int l=0;l<6;l++)
		{
			for(int c=0;c < 3;c++)
			{
				if(i&(1<<cnt))
				{
					mp[l][c] = 1;
					mp[5-l][5-c] = 0;
				}else
				{
					mp[l][c] = 0;
					mp[5-l][5-c] = 1;
				}
				cnt++;
			}
		}
		memset(vis,0,sizeof(vis));
		node_cnt = 1;
		vis[0][0] = 1;
		if(dfs(0,0)==18) ans++;
//		printmp();
//		cin>>cnt;
	}
	cout<<ans/4;   //中心对称算一种,最后还要除以4
	return 0;
} 

最终答案为:509

资料来源 方格分割 二进制枚举+DFS(2017 第八届蓝桥杯省赛A组 第4题)
博客作者 paplion
前往答题
我的笔记