牛客 小乐乐搭积木

链接:https://ac.nowcoder.com/acm/contest/301/B
来源:牛客网

题目描述

小乐乐想要给自己搭建一个积木城堡。
积木城堡我们假设为n*m的平面矩形。
小乐乐现在手里有1*2,2*1两种地砖。
小乐乐想知道自己有多少种组合方案。

输入描述:

第一行输入整数n,m。(1<=n,m<=10)

输出描述:

输出组合方案数。
示例1

输入

复制
2 3

输出

复制
3

说明

示例2

输入

复制
1 3

输出

复制
0
示例3

输入

复制
2 5

输出

复制
8

状压dp
但是之前写铺砖的时候写的很复杂,做这道题的时候看了一下别人的博客用的搜索来找转移状态,学到了。

状压dp利用二进制来表示状态,适用于 n, m 较小的情况(一般都小于等于10)。
在本题中用二进制 1 表示这块方格被砖块覆盖了(不管他是被从哪里过来的砖覆盖的,从上面,下面还是左面都是一样的)用 0 来表示没有被覆盖。
dp[i][j]表示第i列对下一列的影响为j。 j需要被二进制展开,展开后成 (1/0)*2^(m-1),(1/0)*2^(m-2),....(1/0)*2^0
假设 2^(m-1) 的系数为 1 ,这意味着第i行的第m块方块是被一个横着放的1*2砖块覆盖了,所以才对(i+1)行的第m块方块有影响

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 long long dp[11][1050];
 7 int to[10050][2];
 8 int num = 0;
 9 int n, m;
10 void dfs(int l,int pre, int now){
11     if(l>m)
12         return ;
13     if(l==m){
14         to[++num][0] = pre;
15         to[num][1] = now;
16         return ;
17     }
18     dfs(l+1,pre<<1,now<<1|1);
19     dfs(l+2,pre<<2,now<<2);
20     dfs(l+1,pre<<1|1,now<<1);
21 }
22 int main(){
23     scanf("%d%d",&n,&m);
24     memset(dp,0,sizeof(dp));
25     dp[0][0] = 1;
26     if(n>m)swap(n,m);
27     dfs(0,0,0);
28     for(int i=1;i<=n;i++){
29         for(int j=1;j<=num;j++){
30             dp[i][to[j][1]] += dp[i-1][to[j][0]];
31         }
32     }
33     printf("%lld
",dp[n][0]);
34     return 0;
35 }
View Code
原文地址:https://www.cnblogs.com/kongbb/p/10066443.html