题目链接:10913 - Walking on a Grid
题目大意:给出n,k,然后给出一个n*n的图,从(1,1)通过向下,左和右三个方向,走到(n,n)点,途中不可以走相同的位置,并且路过的位置为负数的个数<= k, 找出一条路使得这条路上的值之和最大。不能到达输出impossible
解题思路:记忆化搜索,用四维数组去记录最优解,vis二维数组表示当前访问状态,dp[x][y][i][j]表示位置x,y的地方,当路过的负数个数为i且从j代表的方向进入时的最优解。
我写完的时候超时了,但是改了一下方向就过了,估计是方向的缘故将最优解记录住了,所以优化比较大。
#include <stdio.h> #include <string.h> const int N = 80; const int MAX = -200000000; const int dir[3][2] = {{0, -1}, {0, 1}, {1, 0}}; int n, k, vis[N][N], g[N][N]; long long dp[N][N][10][5], ans; void init() { ans = MAX; memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) for (int x = 0; x < 6; x++) for (int y = 0; y < 3; y++) dp[i][j][x][y] = MAX; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) scanf("%d", &g[i][j]); } void dfs(int x, int y, int cnt, long long sum) { if (cnt > k) return ; if (x == n && y == n) { if (sum > ans) ans = sum; return ; } for (int i = 0; i < 3; i++) { int p = x + dir[i][0]; int q = y + dir[i][1]; if (p > 0 && p <= n && q > 0 && q <= n && vis[p][q] == 0) { vis[p][q] = 1; if (g[p][q] < 0 && dp[p][q][cnt + 1][i] < sum + g[p][q]) { dp[p][q][cnt + 1][i] = sum + g[p][q]; dfs(p, q, cnt + 1, sum + g[p][q]); } else if (g[p][q] >= 0 && dp[p][q][cnt][i] < sum + g[p][q]) { dp[p][q][cnt][i] = sum + g[p][q]; dfs(p, q, cnt, sum + g[p][q]); } vis[p][q] = 0; } } } int main() { int t = 1; while (scanf("%d%d", &n, &k) == 2 && (n || k)) { init(); vis[1][1] = 1; if (g[1][1] >= 0) dfs(1, 1, 0, g[1][1]); else dfs(1, 1, 1, g[1][1]); printf("Case %d: ", t++); if (ans != MAX) printf("%lld\n", ans); else printf("impossible\n"); } return 0; }