Va-10913 Walking on a Grid (memory-based search)
Question: Walking on a Grid
Given a matrix of N * N, each grid has a value. Now we need to go from (1, 1) to (n, n), and we can only go down, left, the three directions on the right go, and a maximum of k negative numbers are required. In this case, the sum of the values that can pass through the grid is the largest.
Solution: perform a memory-based search. However, we need to record the direction. To prevent turning back, we need to record a few negative numbers. Then there is dfs. State transition equation: dp [x] [y] [d] [k] = dp [x + dir [I] [0] [y + dir [I] [1] [I] [k1] + G [x] [y]; d indicates the direction from (x, y. K: number of negative numbers (including the total number of negative numbers of the grids x and y ), k1 depends on G [x + dir [I] [0] [y + dir [I] [1]. If it is positive, it is equal to k, if it is negative, it is equal to k + 1;
Be careful when initializing.
Code:
# Include
# Include
Typedef long ll; const int N = 80; const int M = 3; const ll INF = 0x3f3f3f3f; const int dir [M] [2] = {0, -1 },{ 1, 0 },{ 0, 1 }}; int G [N] [N]; ll dp [N] [N] [6] [M]; int n, k; ll Max (const ll a, const ll B) {return a> B? A: B;} void init () {for (int I = 0; I <n; I ++) for (int j = 0; j <n; j ++) for (int l = 0; l <= k; l ++) for (int m = 0; m <M; m ++) dp [I] [j] [l] [m] =-INF; if (G [0] [0] <0) // (0, 0) at the beginning) if the value of the position is a negative number, the chance of getting a negative number is occupied. K --; for (int l = 0; l <= k; l ++) for (int m = 0; m <M; m ++) dp [n-1] [n-1] [l] [m] = G [n-1] [n-1];} ll DP (int x, int y, int d, int cnt) {int newx, newy; ll & ans = dp [x] [y] [cnt] [d]; if (ans! =-INF) return ans; ll temp; if (d = 1) {// if it is removed, all three directions can be obtained for (int I = 0; I <M; I ++) {newx = x + dir [I] [0]; newy = y + dir [I] [1]; if (newx <0 | newx> = n | newy <0 | newy> = n) continue; if (G [newx] [newy] <0 & cnt = k) continue; if (G [newx] [newy] <0 & cnt <k) {temp = DP (newx, newy, 2-I, cnt + 1); if (temp! =-INF-1) ans = Max (ans, temp + G [x] [y]);} if (G [newx] [newy]> = 0) {temp = DP (newx, newy, 2-I, cnt); if (temp! =-INF-1) ans = Max (ans, temp + G [x] [y]) ;}} else {// if you select left or right, do not select right or left next time. For (int I = (d + 1) % M; I! = D; I = (I + 1) % M) {newx = x + dir [I] [0]; newy = y + dir [I] [1]; if (newx <0 | newx> = n | newy <0 | newy> = n) continue; if (G [newx] [newy] <0 & cnt = k) continue; if (G [newx] [newy] <0 & cnt <k) {temp = DP (newx, newy, 2-I, cnt + 1); if (temp! =-INF-1) ans = Max (ans, temp + G [x] [y]);} if (G [newx] [newy]> = 0) {temp = DP (newx, newy, 2-I, cnt); if (temp! =-INF-1) // calculate ans = Max (ans, temp + G [x] [y]) only when this location is available;} if (ans =-INF) // indicates that the current request cannot reach this grid ans =-INF-1; return ans;} int main () {int cas = 0; while (scanf ("% d", & n, & k), n | k) {for (int I = 0; I <n; I ++) for (int j = 0; j <n; j ++) scanf ("% d", & G [I] [j]); init (); ll ans; ans = DP (0, 0, 1, 0); printf ("Case % d:", ++ cas); if (ans =-INF-1) printf ("impossible \ n"); elseprintf ("% lld \ n", ans);} return 0 ;}