P1990 覆盖墙壁题解

题目

有一个长为N宽为2的墙壁,给你两种砖头:一个长2宽1,另一个是L型覆盖3个单元的砖头。如下图:

0  0
0  00

砖头可以旋转,两种砖头可以无限制提供。你的任务是计算用这两种来覆盖N×2的墙壁的覆盖方法。例如一个2×3的墙可以有5种覆盖方法,如下:

012 002 011 001 011  
012 112 022 011 001

注意可以使用两种砖头混合起来覆盖,如2×4的墙可以这样覆盖:

0112
0012

给定N,要求计算2×N的墙壁的覆盖方法。由于结果很大,所以只要求输出最后4位。例如2×13的覆盖方法为13465,只需输出3465即可。如果答案少于4位,就直接输出就可以,不用加前导0,如N=3时输出5。

输入输出格式

输入格式

一个整数N,表示墙壁的长。

输出格式

输出覆盖方法的最后4位,如果不足4位就输出整个答案。

输入输出样例

输入样例

13

输出样例

3465

解析

此题目采用递推,分好状态是一件非常重要的事情。使用F[N]表示铺满前N*2的面积的墙的方案数;“一列”指长为1,宽为2的墙壁。

1.当这面墙的最后一列被铺满时(如下图所示)

P1990 覆盖墙壁题解_第1张图片

以这种状态结尾的方案数为F[N-1]。

2.当这面墙的最后两列被铺满时(如下图所示,注意颜色的区别)

P1990 覆盖墙壁题解_第2张图片

以这种状态结尾的方案数为F[N-2]。

下面考虑L形的瓷砖,用数组G[N]来表示铺满前(N+1)*2的面积的墙,但是第(N+1)列有一个瓷砖已经被铺过(注意,是已经被铺过!)的方案数。

所以,下面这种情况的方案数就是G[N-2](因为实际上第N列已经铺满了,所以这里要处理的是前N-1列墙,所以多减了1)(如下图所示):

P1990 覆盖墙壁题解_第3张图片

同理,这一种情况的方案数也是G[N-2]:

P1990 覆盖墙壁题解_第4张图片

接下来解决,这个G数组应该怎么维护呢?

首先,第一种情况就是直接先让它变成一个长方形:

P1990 覆盖墙壁题解_第5张图片

以这种状态结尾的方案数为F[N-3]。

第二种情况是,加上一块砖后,它仍然不是一个长方形:

P1990 覆盖墙壁题解_第6张图片

那么第二种情况的方案数就是G[N-3]。

所以,G[N-2](注意,不是G[N])的方案数就等于F[N-3]+G[N-3]。

化简得到:G[N]=F[N-1]+G[N-1]。

所以,F[N]的转移方程就是:

F[N]=F[N-1]+F[N-2]+2*G[N-2](前面说过G[N-2]的情况有两种

而G[N]的转移方程就是:G[N]=F[N-1]+G[N-1]。

初始化:F[0]=1,G[0]=0;F[1]=G[1]=1;

#include
using namespace std;
const int maxn=1000002;
const int mod=10000;
int f[maxn],g[maxn];
int main(){
	int n;
	cin>>n;
	f[0]=1;
	f[1]=g[1]=1;
	for(int i=2;i<=n;i++){
		f[i]=((f[i-1]+f[i-2])%mod+2*g[i-2]%mod)%mod;
		g[i]=(g[i-1]+f[i-1])%mod;
	}
	cout<

你可能感兴趣的:(递推与递归算法专题,动态规划算法专题,算法)