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\n",ans);
101 }
102 return 0;
103 }