第八届蓝桥杯 方格分割

标题:方格分割

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

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

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

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

这里写图片描述 这里写图片描述这里写图片描述


题意:一定要注意经过旋转和对称的为一种情况;

思路一:考试的时候,我是把这个点都编号,从0~35,然后在从0~35 这36个数中选出18个(用的是top之前的不入栈,那个方法,而不是全排列),在选的时候一定要 剪枝(对称点已经在已经选过了,你在再选这个点,有意义吗),把0~35这些点转化为坐标的形式,在判断这些点是不是连通,找出所有满足的情况,再除以4,因为经过 4旋转 就又回到自己的位置了;这个旋转4次,为同一种情况;

如:下面四种为一种情况


答案:509

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

int tt[40],book[40],sum,vis[40][40],sum1;
int a[4][2] = {0,-1,1,0,0,1,-1,0};
struct node
{
	int x,y;
}stu[40];
int check(int x,int y)
{
	if(x>=0&&y>=0&&x<6&&y<6)
		return 1;
	else return 0;
}

int dfs1(int x,int y)
{
	vis[x][y] = 0;
	sum1++;
	if(sum1==18) return 1;
	for(int i = 0;i<4;i++)
	{
		int tx = x + a[i][0];
		int ty = y + a[i][1];
		if(check(tx,ty)&&vis[tx][ty])
			if(dfs1(tx,ty))
				return 1;
	}
	return 0;
}
void dfs(int top,int x)
{
	if(x==19)
	{
		int i;
	
		memset(vis,0,sizeof(vis));
		for(i=1;i<=18;i++)
		{
			int x = stu[tt[i]].x;
			int y = stu[tt[i]].y;
			vis[x][y] = 1;
		}
				
		sum1 = 0;
		if(dfs1(stu[tt[1]].x,stu[tt[1]].y))
			sum++;
		return ;
	}
	for(int i = top;i<36;i++)
	{
		if(book[35-i]) continue;
		book[i] = 1;
		tt[x] = i;
		dfs(i+1,x+1);
		book[i] = 0;
	}
}
int main()
{
	memset(book,0,sizeof(book));
	tt[0] = -1;
	sum = 0;
	for(int i = 0;i<36;i++)
	{
		stu[i].x = i/6;
		stu[i].y = i%6;
	}
	dfs(0,1);
	printf("sum==%d\n",sum/4);
}

第一种方法太耗费时间了,但容易想;

给出的提示:1)记住 dfs 不管拐多少次弯,都是一笔画,所以不做特殊处理,普通dfs是满足不了题目要求的;2)要认真仔细审题; 

要想简单换一种思路

第二种方法,找割线,下面给出的点是,线与线的交点,不是格子的坐标;

思路:仔细观察样例数据可以发现,要满足题目所需要求,只需要剪切的线关于图案的中点中心对称。那么我们可以将格子格子之间接壤的看作边,边与边相交的看作点。则从(3,3)点出发,找一条边到达图案的外圈,不过值得注意的是,从(3,3)出发的是看错两个人出发,两个人的线路一直是对称。所以dfs中标记的时候要一步标记两个。最后的结果要除以4,因为题目中说要旋转对称的是同一种

代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int book[10][10];
int sum; 
int a[4][2] = {0,-1,1,0,0,1,-1,0};
void dfs(int x,int y)
{
	if(x==0||y==0||y==6||x==6)
	{
		sum++;
		return ;	
	}	
	for(int i = 0;i<4;i++)
	{
		int tx = x + a[i][0];
		int ty = y + a[i][1];
		if(book[tx][ty]) continue;
		book[tx][ty] = 1;
		book[6-tx][6-ty] = 1;
		dfs(tx,ty);
		book[tx][ty] = 0;
		book[6-tx][6-ty] = 0;
	}
}
int main()
{
	int i,j;
	sum = 0;
	memset(book,0,sizeof(book));
	book[3][3] = 1;
	dfs(3,3);
	printf("sum==%d\n",sum/4);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值