HDU_3377
这个题目本质上还是一个回路的问题,为了方便处理,可以把初始状态看成只有左上角上方的位置有个下插头,同时把右下角下方的格子看成可以继续走的格子。
由于不一定每个格子都走,所以可以在递推到既没有上插头也没有下插头的格子时额外加一种情况——在这个格子不加任何插头(也就是说不会经过这个格子)。
#include<stdio.h> #include<string.h> #define MAXD 15 #define HASH 30007 #define SIZE 1000010 int N, M, maze[MAXD][MAXD], score[MAXD][MAXD], code[MAXD], ch[MAXD]; struct Hashmap { int head[HASH], next[SIZE], state[SIZE], f[SIZE], size; void init() { memset(head, -1, sizeof(head)); size = 0; } void push(int st, int ans) { int i, h = st % HASH; for(i = head[h]; i != -1; i = next[i]) if(st == state[i]) { if(ans > f[i]) f[i] = ans; return ; } state[size] = st, f[size] = ans; next[size] = head[h]; head[h] = size ++; } }hm[2]; void decode(int *code, int m, int st) { int i; for(i = m; i >= 0; i --) { code[i] = st & 7; st >>= 3; } } int encode(int *code, int m) { int i, cnt = 1, st = 0; memset(ch, -1, sizeof(ch)); ch[0] = 0; for(i = 0; i <= m; i ++) { if(ch[code[i]] == -1) ch[code[i]] = cnt ++; code[i] = ch[code[i]]; st <<= 3; st |= code[i]; } return st; } void init() { int i, j; memset(maze, 0, sizeof(maze)); for(i = 1; i <= N; i ++) for(j = 1; j <= M; j ++) { scanf("%d", &score[i][j]); maze[i][j] = 1; } maze[N + 1][M] = 1; } void shift(int *code, int m) { int i; for(i = m; i > 0; i --) code[i] = code[i - 1]; code[0] = 0; } void dpblank(int i, int j, int cur) { int k, left, up, t; for(k = 0; k < hm[cur].size; k ++) { decode(code, M, hm[cur].state[k]); left = code[j - 1], up = code[j]; if(left && up) { if(left != up) { code[j - 1] = code[j] = 0; for(t = 0; t <= M; t ++) if(code[t] == up) code[t] = left; if(j == M) shift(code, M); hm[cur ^ 1].push(encode(code, M), hm[cur].f[k] + score[i][j]); } } else if(left || up) { if(maze[i][j + 1]) { code[j - 1] = 0, code[j] = left + up; hm[cur ^ 1].push(encode(code, M), hm[cur].f[k] + score[i][j]); } if(maze[i + 1][j]) { code[j - 1] = left + up, code[j] = 0; if(j == M) shift(code, M); hm[cur ^ 1].push(encode(code, M), hm[cur].f[k] + score[i][j]); } } else { if(maze[i + 1][j] && maze[i][j + 1]) { code[j - 1] = code[j] = 13; hm[cur ^ 1].push(encode(code, M), hm[cur].f[k] + score[i][j]); } code[j - 1] = code[j] = 0; if(j == M) shift(code, M); hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]); } } } void solve() { int i, j, cur = 0; hm[cur].init(); memset(code, 0, sizeof(code)); code[1] = 1; hm[cur].push(encode(code, M), 0); for(i = 1; i <= N; i ++) for(j = 1; j <= M; j ++) { hm[cur ^ 1].init(); dpblank(i, j, cur); cur ^= 1; } printf("%d\n", hm[cur].f[0]); } int main() { int t = 0; while(scanf("%d%d", &N, &M) == 2) { init(); printf("Case %d: ", ++ t); solve(); } return 0; }