蓝桥杯 格子刷油漆

问题描述
  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 }

 








posted @ 2019-02-14 00:17  Frontierone  阅读(407)  评论(0编辑  收藏  举报