题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26901#problem/A
题意:有一个 2*n的格子里,你可以选择任意一个格子作为起点,你可以朝着相邻的8个格子行走且一个格子只能被走一次. 问把所有格子都走一遍有多少种方法!
思路:
n=1,n=2的时候特判一下。
n>2的时候就要分两种情况考虑了,第一种是对旁边四个角考虑,另外一种是对中间的考虑。
开一个b[i]数组表示每个当n为i时顶角有多少种走法, c[i]表示中间的格子总共有多少种走法。
对顶角分析:四个顶角等价,只需对左上角一个分析即可。
有三种走法:1、从起点开始,每列只走一格,再绕回来。则有2^(i-1)种走法
2、起点开始,往右或者右下走再回叉一下,再走的话就变成了另外一种顶角走法,则有4*b[i-2]种。
3、起点开始往下走一次,再往右边走,则右边成了一种顶角走法,有2*b[i-1]种。
所以顶角的走法有:b[i]=2^(i-1)+4*b[i-2]+2*b[i-1];
对中间点分析:中间点有左右两个方向的走法,要两者加起来。
这里要注意的是中间点的起点肯定不能一开始就往下(往上)走,那样无法走,所以只能一直往一个方向选择走,遇见顶角之后折回来到达起点的的下面(上面)之后,再往下走就变成了顶角的走法。
不错的递推规律题,赞一个。
1 #include <iostream> 2 #include <cstdio> 3 #include <map> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstring> 7 using namespace std; 8 9 typedef long long lld; 10 const int maxn=1005; 11 const lld mod=1000000007; 12 lld a[maxn], b[maxn], c[maxn], dp[maxn]; 13 14 void init() 15 { 16 memset(c,0,sizeof(c)); 17 dp[1]=2, dp[2]=24; 18 a[0]=1; 19 b[1]=1, b[2]=6; 20 for(int i=1; i<maxn; i++) 21 a[i]=2*a[i-1]%mod; 22 for(int i=3; i<maxn; i++) 23 { 24 b[i]=(a[i-1]+(2*b[i-1]%mod+4*b[i-2]%mod)%mod)%mod; 25 } 26 for(int i=3; i<maxn; i++) 27 { 28 for(int j=1; j<=i-2; j++) 29 { 30 lld tp=((a[j]*4%mod)*b[i-j-1]%mod+(a[i-j-1]*4%mod)*b[j]%mod)%mod; 31 c[i]=(c[i]+tp)%mod; 32 } 33 } 34 for(int i=3; i<maxn; i++) 35 { 36 dp[i]=(c[i]+4*b[i])%mod; 37 } 38 } 39 40 int main() 41 { 42 init(); 43 int n; 44 while(~scanf("%d",&n)) 45 { 46 cout << dp[n] <<endl; 47 } 48 return 0; 49 }