看题解解的。将着色方案映射为40*40*5*5*5*5*2个状态,40*40表示n*m,5*5*5*5表示上下左右相邻块的颜色,0表示未着色。
2表示横切或者竖切。
基本思路是记忆化搜索然后去重,关键点是可能未切前当前块已经着色了。
1 /* 4363 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <algorithm> 12 #include <cstdio> 13 #include <cmath> 14 #include <ctime> 15 #include <cstring> 16 #include <climits> 17 #include <cctype> 18 #include <cassert> 19 #include <functional> 20 #include <iterator> 21 #include <iomanip> 22 using namespace std; 23 //#pragma comment(linker,"/STACK:102400000,1024000") 24 25 #define sti set<int> 26 #define stpii set<pair<int, int> > 27 #define mpii map<int,int> 28 #define vi vector<int> 29 #define pii pair<int,int> 30 #define vpii vector<pair<int,int> > 31 #define rep(i, a, n) for (int i=a;i<n;++i) 32 #define per(i, a, n) for (int i=n-1;i>=a;--i) 33 #define clr clear 34 #define pb push_back 35 #define mp make_pair 36 #define fir first 37 #define sec second 38 #define all(x) (x).begin(),(x).end() 39 #define SZ(x) ((int)(x).size()) 40 #define lson l, mid, rt<<1 41 #define rson mid+1, r, rt<<1|1 42 43 const int mod = 1e9+7; 44 int dp[41][41][5][5][5][5][2]; 45 46 int calc(int x, int y, int u, int d, int l, int r, int dir) { 47 if (dp[x][y][u][d][l][r][dir] >= 0) 48 return dp[x][y][u][d][l][r][dir]; 49 50 int& ret = dp[x][y][u][d][l][r][dir]; 51 52 ret = 0; 53 if ((x==1&&dir==0) || (y==1&&dir==1)) { 54 rep(i, 1, 5) 55 if (i!=u && i!=d && i!=l && i!=r) 56 ++ret; 57 return ret; 58 } 59 60 if (dir) { 61 rep(i, 1, y) { 62 rep(j, 1, 5) { 63 if (j!=u && j!=d && j!=l) { 64 ret = (ret + calc(x, y-i, u, d, j, r, 0)) % mod; 65 } 66 if (j!=u && j!=d && j!=r) { 67 ret = (ret + calc(x, i, u, d, l, j, 0)) % mod; 68 } 69 } 70 } 71 72 int tmp = 0; 73 rep(i, 1, 5) { 74 if (i!=u && i!=d && i!=l) { 75 rep(j, 1, 5) { 76 if (j!=u && j!=d && j!=r && j!=i) 77 ++tmp; 78 } 79 } 80 } 81 82 ret = (ret + mod - tmp*(y-1)) % mod; 83 rep(i, 1, 5) 84 if (i!=u && i!=l && i!=r && i!=d) 85 ++ret; 86 87 ret %= mod; 88 } else { 89 rep(i, 1, x) { 90 rep(j, 1, 5) { 91 if (j!=u && j!=l && j!=r) { 92 ret = (ret + calc(x-i, y, j, d, l, r, 1)) % mod; 93 } 94 if (j!=d && j!=l && j!=r) { 95 ret = (ret + calc(i, y, u, j, l, r, 1)) % mod; 96 } 97 } 98 } 99 100 int tmp = 0; 101 rep(i, 1, 5) { 102 if (i!=u && i!=l && i!=r) { 103 rep(j, 1, 5) { 104 if (j!=d && j!=l && j!=r && j!=i) 105 ++tmp; 106 } 107 } 108 } 109 110 ret = (ret + mod - tmp*(x-1)) % mod; 111 rep(i, 1, 5) 112 if (i!=u && i!=l && i!=r && i!=d) 113 ++ret; 114 115 ret %= mod; 116 } 117 118 return ret; 119 } 120 121 int main() { 122 ios::sync_with_stdio(false); 123 #ifndef ONLINE_JUDGE 124 freopen("data.in", "r", stdin); 125 freopen("data.out", "w", stdout); 126 #endif 127 128 int t; 129 int n, m; 130 int ans; 131 132 memset(dp, -1, sizeof(dp)); 133 scanf("%d", &t); 134 while (t--) { 135 scanf("%d %d", &n, &m); 136 ans = calc(n, m, 0, 0, 0, 0, 0); 137 printf("%d\n", ans); 138 } 139 140 #ifndef ONLINE_JUDGE 141 printf("time = %d.\n", (int)clock()); 142 #endif 143 144 return 0; 145 }