HDU 1693 Eat the Trees 插头DP
这是一道入门题,只需判断插头有无。
具体分为:
1、上插头和左插头都有
2、有上插头或有左插头
3、上插头和左插头都没有
用HASHMAP储存状态,具体有一些小技巧(见程序)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 7 using namespace std; 8 9 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i) 10 #define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i) 11 #define mset(a, b) memset(a, b, sizeof(a)) 12 typedef long long LL; 13 const int MAXD = 15, HASH = 10007, STATE = 100010; 14 int n, m, maze[MAXD][MAXD]; 15 int code[MAXD]; 16 struct HASHMAP 17 { 18 int head[HASH], nxt[STATE], siz, state[STATE]; LL f[STATE]; 19 void clear() { siz = 0, mset(head, -1); } 20 void push(int x, LL add) 21 { 22 int pos = x%HASH, i = head[pos]; 23 for (; i != -1; i = nxt[i]) 24 if (state[i] == x) 25 { f[i] += add; return ; } 26 state[siz] = x, f[siz] = add; 27 head[pos] = siz, nxt[siz++] = head[pos]; 28 } 29 }hm[2]; 30 31 void in() 32 { 33 scanf("%d %d", &n, &m), mset(maze, 0); 34 REP(i, 1, n) 35 REP(j, 1, m) scanf("%d", &maze[i][j]); 36 } 37 38 void decode(int s) 39 { 40 REP(i, 0, m) 41 if (s&(1<<i)) code[i] = 1; 42 else code[i] = 0; 43 } 44 45 int encode() 46 { 47 int ret = 0; 48 DWN(i, m, 0) ret = ret*2+code[i]; 49 return ret; 50 } 51 52 void shift(int j) 53 { 54 if (j != m) return ; 55 DWN(i, m, 1) code[i] = code[i-1]; code[0] = 0; 56 } 57 58 void dp_blank(int i, int j, int cur) 59 { 60 REP(k, 0, hm[cur].siz-1) 61 { 62 decode(hm[cur].state[k]); 63 int lef = code[j-1], up = code[j]; 64 if (lef && up) 65 { 66 code[j-1] = code[j] = 0, shift(j); 67 hm[cur^1].push(encode(), hm[cur].f[k]); 68 } 69 else 70 { 71 if (lef || up) 72 { 73 if (maze[i+1][j]) 74 { 75 code[j-1] = 1, code[j] = 0, shift(j); 76 hm[cur^1].push(encode(), hm[cur].f[k]); 77 } 78 if (maze[i][j+1]) 79 { 80 code[j-1] = 0, code[j] = 1; 81 hm[cur^1].push(encode(), hm[cur].f[k]); 82 } 83 } 84 else 85 if (maze[i+1][j] && maze[i][j+1]) 86 { 87 code[j-1] = code[j] = 1, shift(j); 88 hm[cur^1].push(encode(), hm[cur].f[k]); 89 } 90 } 91 } 92 } 93 94 void dp_block(int i, int j, int cur) 95 { 96 REP(k, 0, hm[cur].siz-1) 97 { 98 decode(hm[cur].state[k]); 99 code[j-1] = code[j] = 0, shift(j); 100 hm[cur^1].push(encode(), hm[cur].f[k]); 101 } 102 } 103 104 void work() 105 { 106 int cur = 0; LL ans = 0; 107 hm[0].clear(), hm[0].push(0, 1); 108 REP(i, 1, n) 109 REP(j, 1, m) 110 { 111 hm[cur^1].clear(); 112 if (maze[i][j]) dp_blank(i, j, cur); 113 else dp_block(i, j, cur); 114 cur ^= 1; 115 } 116 REP(i, 0, hm[cur].siz-1) ans += hm[cur].f[i]; 117 printf("There are %I64d ways to eat the trees.\n", ans); 118 } 119 120 int main() 121 { 122 int T; 123 scanf("%d", &T); 124 REP(i, 1, T) 125 { 126 printf("Case %d: ", i); 127 in(), work(); 128 } 129 return 0; 130 }
Nothing is impossible!