1 //插头DP,算是广义路径的吧。 2 /* 3 我是这样想的,定义填数的为0,未填的为1.然后,初始自然是(0,0).我还定义了整个棋盘的状态,不知是否多此一举。 4 这样,把轮廓线上的格子状态记录。当(I,J)上方的格子为空,必定要填一个竖的。当左边格子为空,当前可填一个横的,也可不填。 5 当左边格子不为空,当前格子必为空。。。AC. 6 */ 7 8 #include <iostream> 9 #include <cstdio> 10 using namespace std; 11 int n,m; 12 int code[15]; 13 const int MAXL=6000; 14 const int MAXM=1000000; 15 struct HASHMAP{ 16 int hash[MAXL],next[MAXM]; 17 __int64 f[MAXM]; int state[MAXM],alst[MAXM]; 18 int size; 19 void init(){ 20 size=0; 21 memset(hash,-1,sizeof(hash)); 22 } 23 void push(int st,__int64 ans,int als){ 24 int h=st%MAXL; 25 for(int i=hash[h];i!=-1;i=next[i]){ 26 if(state[i]==st){ 27 f[i]+=ans; 28 return ; 29 } 30 } 31 f[size]=ans; 32 state[size]=st; 33 alst[size]=als; 34 next[size]=hash[h]; 35 hash[h]=size++; 36 } 37 }hm[2]; 38 39 void decode(int st){ 40 for(int i=1;i<=m;i++){ 41 code[i]=(st&1); 42 st=(st>>1); 43 } 44 } 45 46 int encode(){ 47 int st=0; int i; 48 for(i=m;i>1;i--){ 49 st=(st|code[i]); 50 st=(st<<1); 51 } 52 st=(st|code[i]); 53 return st; 54 } 55 56 void dp(int i,int j,int cur){ 57 for(int e=0;e<hm[cur].size;e++){ 58 decode(hm[cur].state[e]); 59 int als=hm[cur].alst[e]; 60 if(code[j]==1){ 61 code[j]=0; als--; 62 hm[cur^1].push(encode(),hm[cur].f[e],als); 63 } 64 else{ 65 if(code[j-1]==1){ 66 code[j]=1; 67 hm[cur^1].push(encode(),hm[cur].f[e],als+1); 68 code[j]=code[j-1]=0; 69 hm[cur^1].push(encode(),hm[cur].f[e],als-1); 70 } 71 else{ 72 code[j]=1; 73 hm[cur^1].push(encode(),hm[cur].f[e],als+1); 74 } 75 } 76 } 77 } 78 79 80 int main(){ 81 int i,j; 82 while(scanf("%d%d",&n,&m)!=EOF){ 83 if(!n&&!m) break; 84 code[0]=0; 85 int cur=0; 86 hm[cur].init(); 87 hm[cur].push(0,1,0); 88 for(i=1;i<=n;i++) 89 for(j=1;j<=m;j++){ 90 hm[cur^1].init(); 91 dp(i,j,cur); 92 cur=cur^1; 93 } 94 __int64 ans=0; 95 for(i=0;i<hm[cur].size;i++){ 96 if(hm[cur].alst[i]==0){ 97 ans+=hm[cur].f[i]; 98 } 99 } 100 printf("%I64d ",ans); 101 } 102 return 0; 103 }