第十届蓝桥杯大赛软件类决赛C/C++ 大学B组 试题C: 拼接

第十届蓝桥杯大赛软件类决赛C/C++ 大学B组 试题C: 拼接 解答

【问题描述】
小明要把一根木头切成两段,然后拼接成一个直角。
如下图所示,他把中间部分分成了n * n 的小正方形,他标记了每个小正方
形属于左边还是右边。然后沿两边的分界线将木头切断,将右边旋转向上后拼
接在一起。
第十届蓝桥杯大赛软件类决赛C/C++ 大学B组 试题C: 拼接_第1张图片
要求每个小正方形都正好属于左边或右边,而且同一边的必须是连通的。
在拼接时,拼接的部位必须保持在原来大正方形里面。
请问,对于7 *7 的小正方形,有多少种合法的划分小正方形的方式。

#include 
using namespace std;

int ans = 0;
void invert(int n, int** a,int** b)
{
     
	for (int i = 0; i < n; i++)
	{
     
		*((int *)b+n*i+n-1-i)=*((int *)a+n*i+n-1-i);
	}
	
	for (int i = 0; i < n - 1; i++)
	{
     
		for (int j = 0, k = n - 1 - i; j < n - 1 - i; j++, k--)
		{
     
		    *((int *)b+n*i+j)=*((int *)a+n*(i+k)+j+k);
			*((int *)b+n*(i+k)+j+k)=*((int *)a+n*i+j);
		}
	}
}

void f(int loop,int n, int** left, int** right)
{
     
	if (loop == 0)
	{
     
		int mid[n][n] = {
     };
		bool flag = true;
		
		invert(n, right,(int **)  mid);
		
		for (int i = 0; i < n; i++)
		{
     
			for (int j = 0; j < n; j++)
			{
     
				mid[i][j] += *((int*)left + n * i + j);
			}
		}
		
		for (int i = 0; i < n; i++)
		{
     
			for (int j = 0; j < n; j++)
			{
     
				if (mid[i][j] != 1) flag = false;
			}
		}
		if (flag == true) ans++;
	}
	else
	{
     
		for (int i = 0; i < n + 1; i++)
		{
     
			for (int l = 0; l < i; l++)
			{
     
				*((int*)left + (n - loop) * n + l) = 1;
				*((int*)right + (n - loop) * n + l) = 0;
			}
			for (int r = i; r < n; r++)
			{
     
				*((int*)left + (n - loop) * n + r) = 0;
				*((int*)right + (n - loop) * n + r) = 1;
			}
			f(loop - 1, n, left, right);
		}
	}
}

int main(void)
{
     
	int n;
	cout << "input n=";
	cin >> n;
	int left[n][n] = {
     };
	int right[n][n] = {
     };
	f(n, n, (int **) left, (int **) right);
	cout << ans << endl;
	return 0;
}

思路就是用left,right两个数组表示切分情况,其中元素0表示不在这边,元素1表示在这边,通过递归对切分情况进行穷举,对每一种切分进行判断,将right以次对角线为轴进行翻转,最后将两个数组矩阵相加,若为一个全1阵则算正确拼接。最后的结果是对于n*n的正方形,ans=2^n,题目答案就是128。

你可能感兴趣的:(笔记,c++,数组)