蓝桥杯 格子刷油漆
问题描述
X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
A | B | C |
D | E | F |
比如:a d b c e f 就是合格的刷漆顺序。 c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。
输入格式 输入数据为一个正整数(不大于1000)
输出格式 输出数据为一个正整数。 样例输入 2 样例输出 24 样例输入 3 样例输出 96 样例输入 22 样例输出 359635897
用a[i]表示从某一角到刷完i列终点任意的情况数。b[i]表示从某一角到刷完i列,终点与起点同列的情况数
分析:
一、如果从角出发,有三种情况
①:一列一列的走(A-D-B-E或A-D-E-B),那么走到下一列有上下的选择,故a[i]=2*a[i-1]
②:走到下一列再回到上一列再去往下下一列(A-B-D-E-C-F或A-E-D-B-C-F或A-B-D-E-F-C或A-E-D-B-F-C)所以a[i]=2*2*a[i-2]
③:走到下一列再继续走下一列,那么就必须一直走到结尾再回来,不然两边都有空。 b[i]=2*b[i-1]
二、如果从中间出发,那么就是分成两个矩形。先左边按照③走,另一个随意走。然后再右边按照③走,另一个随意走
那么就是2*(2*b[i-1]*2*a[n-i]+2*b[n-i]*2*a[i-1])
红色2:从第i列可以有左右两个选择
绿色2:从第i列开始左走有上下连个选择,此时必须按③走,所以b[i-1]。回到第i列往右走有上下两个选择,此时随意走。然后先右后左同理。
但是取摸还是有点不太理解。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1010; 4 const int mod=1000000007; 5 typedef long long ll; 6 ll a[maxn],b[maxn]; 7 int n; 8 9 int main() { 10 while(~scanf("%d",&n)) { 11 if(n==1) puts("2"); 12 else { 13 a[1]=1; 14 a[2]=6; 15 b[1]=1; 16 b[2]=2; 17 for(int i=3;i<=n;i++) { 18 b[i]=b[i-1]*2%mod; 19 a[i]=(2*a[i-1]+4*a[i-2]+b[i])%mod; 20 } 21 ll sum=4*a[n]%mod; 22 for(int i=2;i<n;i++) { 23 sum=sum+(8*b[i-1]*a[n-i]%mod+8*b[n-i]*a[i-1]%mod); 24 sum=sum%mod; 25 } 26 printf("%lld\n",sum); 27 } 28 } 29 return 0; 30 }
埋骨何须桑梓地,人生无处不青山