题目链接: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;
- }