WA点:我把所有的转移都在纸上写出来了后,发现有些情况是重复的,于是手贱给删掉了... 这样就少计算了一些情况,或者说删掉后,一个可行状态对应的方案数要乘一个常数。
做法:对于一行来说,1代表在此行填充,0代表未在此行填充(也就是需要靠上一行来填充),其实就是枚举上一行的填充状态然后推出下一行的所有可行状态,然后保存起来即可。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
using namespace std;
int s[80005],ss[80005],cnt;
long long dp[15][1<<9];
void dfs(int i,int s1,int s2,bool can)
{
if(i<0)
return ;
if(i==0)
{
s[cnt]=s1;
ss[cnt]=s2;
cnt++;
return ;
}
//0 不放6
dfs(i-1,s1<<1,(s2<<1)+1,false);
//0 放6
dfs(i-2,(s1<<2)+1,s2<<2,false);
//1
dfs(i-1,(s1<<1)+1,s2<<1,false);
//2 不放6
dfs(i-2,(s1<<2)+3,(s2<<2)+3,false);
//2 放6
dfs(i-3,(s1<<3)+7,(s2<<3)+4,false);
//3
dfs(i-2,(s1<<2)+3,(s2<<2)+2,false);
//4 不放6
dfs(i-2,(s1<<2)+3,(s2<<2)+1,false);
//4 放6
dfs(i-3,(s1<<3)+7,s2<<3,false);
//5 什么也不放
dfs(i-2,(s1<<2)+2,s2<<2,false);
//5 放2 不放6
dfs(i-3,(s1<<3)+7,(s2<<3)+1,false);
//5 放2 放6
dfs(i-4,(s1<<4)+15,s2<<4,false);
//5 放3
dfs(i-3,(s1<<3)+7,s2<<3,false);
}
int main()
{
int n,m,i,j;
while(cin>>m>>n)
{
cnt=0;
dfs(m,0,0,false);
// cout<<cnt<<endl;
memset(dp,0,sizeof(dp));
dp[0][(1<<m)-1]=1;
for(i=1;i<=n;++i)
{
for(j=0;j<cnt;++j)
{
dp[i][s[j]]+=dp[i-1][ss[j]];
}
}
printf("%lld\n",dp[n][(1<<m)-1]);
}
return 0;
}