1、经典的骨牌覆盖问题,用轮廓线动态规划解决。。。看了好几个小时,终于明白了。数据有点BT,会重复,所以要用数组保存算过的值,注意memo的大小是【maxn*maxn】【maxn*maxn】的,因为最小值m<=10不意味着m,n均小于等于10,极端数据是1,100。
2、滚动数组以及异或运算的运用很巧妙。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,cur;
const int maxn=15;
long long d[2][1<<maxn],memo[maxn*maxn][maxn*maxn];
void update(int a,int b){
if(b&(1<<m)) d[cur][b^(1<<m)]+=d[1-cur][a];
}
int main(){
memset(memo,-1,sizeof(memo));
while(scanf("%d%d",&n,&m)==2){
if(n<m) swap(n,m);
if(memo[n][m]>=0){
printf("%lld\n",memo[n][m]);
continue;
}else{
memset(d,0,sizeof(d));
cur=0;
d[0][(1<<m)-1]=1;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
cur^=1;
memset(d[cur],0,sizeof(d[cur]));
for(int k=0;k<(1<<m);k++){
update(k,k<<1);
if(i&&!(k&(1<<(m-1)))) update(k,(k<<1)|(1<<m)|1);
if(j&&!(k&1)) update(k,(k<<1)|3);
}
}
printf("%lld\n",memo[n][m]=d[cur][(1<<m)-1]);
}
}
return 0;
}