2022蓝桥杯 积木画 题解

积木画

题目链接

题目描述
小明最近迷上了积木画,有这么两种类型的积木,分别为 I 型(大小为 2 个单位面积)和 L 型(大小为 3 个单位面积):

在这里插入图片描述

同时,小明有一块面积大小为 2 × N 的画布,画布由 2 × N 个 1 × 1 区域构成。小明需要用以上两种积木将画布拼满,他想知道总共有多少种不同的方式? 积木可以任意旋转,且画布的方向固定。

输入
输入一个整数 N,表示画布大小。
输出
输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取模后的值。
样例输入
3
样例输出
5
提示
五种情况如下图所示,颜色只是为了标识不同的积木:

在这里插入图片描述

对于所有测试用例,1 ≤ N ≤ 10000000.

解题思路

一个2行n列的方格,铺上I型或者L型的积木,问:有多少种铺法。那就,dp嘛,啊当然我比赛时是一点都没去写这道题(太菜了)。
我的解题思路是基于这两个积木的形状,不论它怎么旋转,都不会超过2*2的方格,也就是说,当我从左往右放置积木时,不论我怎么胡乱旋转,顶多影响到下一列。所以我们可以根据上一列的积木空缺情况来判断放置什么样的积木,然后放置好积木之后,当前这一列的空缺情况又会影响到下一列如果放置。

那么,有哪些不同情况呢,咱们来分析一波。
比如说我用数组a[x][y]表示第i列积木的放置情况,用数组b[x][y]表示第i+1列积木的放置情况,x代表上面那行,y代表下面那行,如果是没有积木的那就是0,如果有积木就是1。
那么从i到i+1列的时候,就是基于第i列的情况。比如说第i列都是满的,即a[1][1],那么i+1列可以是b[0][0]。如果第i列上面铺了积木但是下面是空的,即a[1][0],那么i+1列可以在下面位置横着放一个I型积木,即b[0][1],也可以是放一个旋转过来的L型积木,即b[1][1]。反过来,如果第i列上面没有铺积木,下面有铺积木,同样的道理,第i+1列可以是b[1][0]或者b[1][1]。还有一种情况就是第i列上下都是空的,那么第i+1列可以直接放一个竖着的I型积木;也可以横着放两个I型积木,然后再下一列就是x=1,y=1;当然也可以放L型,那么再下一列就是x=1,y=0或者x=0,y=1。

接下来就是对每一列都这样判断一遍…把所有的可以放置的方案累加起来,然后把b的值加到a上面,再清空b数组,下一轮循环判断积木放置情况的时候继续使用…最后a数组就是所有方案数的总和…

代码如下:

#include<bits/stdc++.h>
using namespace std;

int n,a[2][2],b[2][2];
const int N=1e9+7;

void add(int &x,int y)
{
	x+=y;
	x%=N;
}

int main()
{
	scanf("%d",&n);
	a[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		memset(b,0,sizeof(b));//清空用来放下一列的情况的数组
		//第i列上下都是空的
		add(b[0][0],a[0][0]);//可以空着
		add(b[1][1],a[0][0]);//可以竖着放一个I型积木
		add(b[0][1],a[0][0]);//可以放一个L型积木
		add(b[1][0],a[0][0]);//放L型积木的另一种放法
		//第i列上面有积木,下面是空的
		add(b[0][1],a[1][0]);//可以在下面横着放一个I型积木
		add(b[1][1],a[1][0]);//可以放一个L型积木
		//第i列下面有积木,上面是空的
		add(b[1][0],a[0][1]);//可以在上面横着放一个I型积木
		add(b[1][1],a[0][1]);//可以放一个L型积木
		//第i列上下都有积木
		add(b[0][0],a[1][1]);//下一列一定都是空的
		
		memcpy(a,b,sizeof(a));//把下一列的情况加到a数组里面,下一轮循环的时候b数组清空了就可以再次用来存后面那一列的情况了。
	}
	printf("%d\n",a[0][0]);
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值