历届试题格子刷油漆
时间限制:1.0s 内存限制:256.0MB
问题描述
X国的一段古城墙的顶端可以看成2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:ad b c e f就是合格的刷漆顺序。
ce f d a b是另一种合适的方案。
当已知N时,求总的方案数。当N较大时,结果会迅速增大,请把结果对1000000007(十亿零七)取模。
输入格式
输入数据为一个正整数(不大于1000)
输出格式
输出数据为一个正整数。
样例输入
2
样例输出
24
样例输入
3
样例输出
96
样例输入
22
样例输出
359635897
思路:较麻烦的dp,要考虑好多情况, 看了一位大神的代码才明白。
//格子刷油漆
#include <stdio.h>
#define MAX_NUM 1000000007
__int64 a[1001] = {0}, b[1001] = {0}; //a[]为从角落的一个格子开始刷的总可能数, b[]为从角落的一个格子开始刷最终回到起始格子的正下方
int main()
{
int n, i;
__int64 sum;
scanf("%d", &n);
b[1] = 1; //初始化b[1], 显而易见b[1] = 1
for(i = 2; i <= n; i++) //因为要回到起点下方, 所以每列格子都有一来一回两个, 除第一列, b[i] = 2*b[i-1]
{
b[i] = (b[i-1] * 2) % MAX_NUM;
}
a[1] = 1; //初始化一下a[1],a[2], 因为递推时要用到(至于a[1,2]怎样得到的,自己数吧)
a[2] = 6;
for(i = 3; i <= n; i++) //a[i]可以由三部分得来,1,i=1时先走起点下方的格子然后的落点有两种(后面就和a[i]一样了)。2,最终回到起点正下方(即b[i])。3,由i-2列辗转的来(如图)
{
a[i] = (2 * a[i-1] + b[i] + 4 * a[i-2]) % MAX_NUM;
}
sum = 4 * a[n]; //sum是四个角为起点的情况和中间为起点的情况之和
for(i = 2; i <= n-1; i++) //中间为起点
{
sum = (sum + 2*2*a[n-i]*2*b[i-1] + 2*2*a[i-1]*2*b[n-i]) % MAX_NUM; //中间为起点的情况可分为先向前和先向后两种, 因为必须经过正下方的格子所以必须有一半是b[i-1], 一半是a[i-1]得来
}
printf("%I64d\n", sum);
return 0;
}