时间限制:1.0s 内存限制:256.0MB
问题描述
X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。
c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。
输入格式
输入数据为一个正整数(不大于1000)
输出格式
输出数据为一个正整数。
样例输入
2
样例输出
24
样例输入
3
样例输出
96
样例输入
22
样例输出
359635897
题解:
设a[x]为4个角中任意一个格子为起始点的总方案数,b[x]为4个角中任意一个格子为起始点,其上或者其下的格子为终点的方案数。
对于b[x],后面的每一列都必须有1个格子过去1个格子回来才能回到终点,所以b[x]=2*b[x-1];
对于a[x],以左上角的格子为例,有三个方向可以走,分类如下:

起点在角上的总方案数
起点在中间的总方案数
#include<iostream>
#define ll long long
#define inf 1000000007
using namespace std;
ll a[1011],b[1011];
int main()
{
int n;
scanf("%d",&n);
b[1]=1,a[1]=1;
b[2]=2,a[2]=6;
for(int i=3;i<=n;i++){
b[i]=b[i-1]*2%inf;
a[i]=(2*a[i-1]+4*a[i-2]+2*b[i-1])%inf;
}
ll ans1,ans2;
if(n==1){
printf("2\n");
}else{
ans1=4*a[n]%inf;
ans2=0;
for(int i=2;i<n;i++)
ans2+=8*(b[i-1]*a[n-i]%inf+b[n-i]*a[i-1]%inf)%inf;
printf("%lld\n",(ans1+ans2)%inf);
}
return 0;
}
本文详细解析了一道经典算法题“历届试题格子刷油漆”,通过动态规划的方法,计算2*N矩阵格子的所有刷漆方案数,特别关注了边界条件和状态转移方程的设计。
6253

被折叠的 条评论
为什么被折叠?



