格子刷油漆
题目:格子刷油漆
链接:http://lx.lanqiao.org/problem.page?gpid=T38
题意:要遍历2行n列的格子,一次只能遍历四周,遍历过就不能再遍历,问有多少种遍历方法(起点也任意,只要能遍历完所有格子就可以)
思路:
分两大块:
1.从某一个角落出发:A[n]
比如从A点出发,因为要遍历所有的格子,所以要想遍历同一列的D,就只有三种方法:
1. 直接到D,然后再遍历BCEF这块,那么这种情况的数量就是2*A[n-1],因为B、E你可以选一个开始,所以乘2。
2. 先遍历右边所有格子,最后回到D点,把这种走法的数量记录在d[]数组,那么d[n]=2*d[n-1],同样,B、E可以选一个。
3. 先遍历B、E中的一个再遍历D再遍历B、E中的另一个,再遍历CF后面的,这种情况的数量是2*2*A[n-2],因为B、E可以选一个,C、F也可以选一个。
很容易可以理解只有前面三种情况才可能从A出发遍历到D,那么从角落出发的情况总数为:4*A[n]; A[n]=d[n]+2*A[n-1]+4*A[n-2];
2.从中间的某个格子从发:
如果从中间的某个格子出发,那么肯定要先遍历完左边所有格子或者右边所有格子才能遍历同一列的格子,不然就隔断了,那么对于第i列,他的情况数量为:2*(2*d[i-1]*2*A[n-i]+2*d[n-i]*2*A[i-1]);
分成上面两种情况后,问题就很简单了,只要将两种情况所有可能加起来就可以得到答案了。
1 #include<stdio.h> 2 #define Mod 1000000007 3 typedef long long LL; 4 5 LL d[1010]; 6 LL a[1010]; 7 8 int main() 9 { 10 d[1]=1; 11 for(int i=2;i<1010;i++) 12 d[i]=2*d[i-1]%Mod; 13 int n; 14 while(scanf("%d",&n)!=EOF) 15 { 16 if(n==1) 17 { 18 printf("2\n"); 19 continue; 20 } 21 LL sum=0; 22 a[1]=1,a[2]=6; 23 for(int i=3;i<=n;i++) 24 { 25 a[i]=(d[i]+2*a[i-1]+4*a[i-2])%Mod; 26 } 27 sum=4*a[n]; 28 for(int i=2;i<n;i++) 29 { 30 sum=(sum+2*(4*d[i-1]*a[n-i]%Mod+4*d[n-i]*a[i-1]%Mod)%Mod)%Mod; 31 } 32 printf("%I64d\n",sum); 33 } 34 return 0; 35 }