题目链接:https://www.acwing.com/problem/content/description/293/
题目给出一个n*m的方格,问用1*2的方块去拼,有多少种方案,由于每一行只跟上一行的状态有关系,所以可以把行数作为“阶段”,其次,每行的状态用01表示,0表示对下一行没有影响,1表示需要下一行拼另一半,这样的话状态设计就是前i行且第i行的状态是j的方案的数量。转移的时候注意,第i-1行是1的时候下面一个一定是0,第i-1行是0的时候是没有影响的,所以两个状态j&k==0,而且除了1下面的0以外的地方,其他地方都是通过横着的1*2方块去拼的,所以一定0一定是连续的偶数,这里可以先预处理出来,处理的时候设置一个1位二进制数记录,并且在假设第m位是1的情况之下把最后一段连续0也算在里面。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll f[12][1<<11]; bool v[1<<11]; int n,m; int main(){ while(cin>>n>>m && n){ memset(f,0,sizeof f); for(int i=0;i<1<<m;i++){ int has_odd=0,cnt=0; for(int j=0;j<m;j++){ if(i>>j & 1)has_odd|=cnt,cnt=0; else cnt^=1; } v[i]=has_odd|cnt ? 0 : 1; } f[0][0]=1; for(int i=1;i<=n;i++){ for(int j=0;j<1<<m;j++){ for(int k=0;k<1<<m;k++){ if((j&k)==0 && v[j|k]) f[i][j]+=f[i-1][k]; } } } cout<<f[n][0]<<endl; } }
原文:https://www.cnblogs.com/randy-lo/p/13413266.html