棋盘覆盖

 1 /*
 2   题意:用1*2覆盖n*m的区域的方案数,n<=1000,m<=5
 3   思路:枚举每层的状态,计算状态之间的转移。则dp[i][j]=sum(dp[i-1][k]*a[k][j])其中k为前一层状态,j为当前层状态。
 4         状态之间的转移,可以枚举当前层的放置方案,
 5   时间:2018.07.18
 6 */
 7 #include <bits/stdc++.h>
 8 using namespace std;
 9 
10 typedef long long LL;
11 const int MAXN=100005;
12 const LL MOD7 = 1e9+7;
13 
14 int a[1<<5][1<<5];
15 LL dp[1005][1<<5];
16 int n,m;
17 
18 void dfs(int state1,int state2,int state,int depth)
19 {
20     // printf("state1=%d state2=%d state=%d depth=%d\n",state1,state2,state,depth);
21     // printf("%d %d\n",(state&(1<<depth)), (state2&(1<<depth)));
22     if (depth==m)
23     {
24         if (state==(1<<m)-1) ++a[state1][state2];
25         return ;
26     }
27     if ((state&(1<<depth))==0 && (state2&(1<<depth))!=0) dfs(state1,state2,state+(1<<depth),depth+1);
28     if ((state&(1<<depth))==0 && (state2&(1<<depth))==0)
29     {
30         if (depth+1<m && (state&(1<<(depth+1)))==0) dfs(state1,state2,state+(1<<depth)+(1<<(depth+1)),depth+1);
31         return;
32     }
33     if ((state&(1<<depth))!=0 && (state2&(1<<depth))!=0) return;
34     dfs(state1, state2, state, depth+1);
35 }
36 
37 void init()
38 {
39     for (int i=0;i<(1<<m);++i)
40     {
41         for (int j=0;j<(1<<m);++j)
42         {
43             dfs(i,j,i,0);
44         }
45     }
46 //    for (int i=0;i<(1<<m);++i)
47 //    {
48 //        for (int j=0;j<(1<<m);++j)
49 //        {
50 //            printf("%d ",a[i][j]);
51 //        }
52 //        printf("\n");
53 //    }
54 }
55 
56 int main()
57 {
58 #ifndef ONLINE_JUDGE
59     freopen("test.txt","r",stdin);
60 #endif // ONLINE_JUDGE
61     scanf("%d%d",&n,&m);
62     init();
63     LL ans=0;
64     dp[0][(1<<m)-1]=1;
65     for (int i=1;i<=n+1;++i)
66     {
67         for (int j=0;j<(1<<m);++j)
68         {
69             for (int k=0;k<(1<<m);++k)
70             {
71                 dp[i][j]=(dp[i][j]+a[k][j]*dp[i-1][k])%MOD7;
72             }
73         }
74     }
75     printf("%lld\n",dp[n+1][0]);
76     return 0;
77 }

 

转载于:https://www.cnblogs.com/LeeSongt/p/9332987.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值