Lightoj 1071 - Baker Vai (双线程DP)

题目连接:

  http://lightoj.com/volume_showproblem.php?problem=1071

题目大意:

  一个n*m的格子,Baker Vai要从(1,1)到(n,m)再回到(1,1),每到一个格子可以收集格子上的数字(每个格子只能走一次,(1,1)这个格子除外),问最终搜集的数字之和最大为多少?

解题思路:

  可以把题目转化为求两个对象同时从(1,1)出发到(n,m)途中不能相遇,状态转移的时候可以用dp[step][x][y],step代表当前步数,x,y分别代表两者当前所在的行(所在列可以直接求出来)。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 105;
 4 const int INF = 0x3f3f3f3f;
 5 
 6 int Map[maxn][maxn], dp[maxn*2][maxn][maxn];
 7 int n, m;
 8 int dfs (int step, int x, int y)
 9 {
10     if (step == n + m - 2)
11     {//走到够了步数
12         if (x==y && x==n-1 && step-x==m-1)
13             return Map[n-1][m-1];//刚好到了终点
14         else
15             return -INF;//不合法
16     }
17     int ans = dp[step][x][y];
18     if (ans != -1)//前面已经搜过,直接返回
19         return ans;
20     if (x<n-1 && y<n-1)//x,y都向下走
21         ans = max(ans, dfs(step+1, x+1, y+1));
22     if (x<n-1 && step-y<m-1)//x向下走.y向右走
23         ans = max(ans, dfs(step+1, x+1, y));
24     if (step-x<m-1 && y<n-1)//x向右走.y向下走
25         ans = max(ans, dfs(step+1, x, y+1));
26     if (step-x<m-1 && step-y<m-1)//x,y都向右走
27         ans = max(ans, dfs(step+1, x, y));
28     ans += Map[x][step-x];//选择以上四种情况最优的一种,再加上当前的
29     if (x != y)//如果相同的话就不加,因为不走重复的一定比走重复的的要大
30         ans += Map[y][step-y];
31     dp[step][x][y] = ans;
32     return ans;
33 
34 }
35 int main ()
36 {
37     int t, Case = 0;
38     scanf ("%d", &t);
39     while (t --)
40     {
41         scanf ("%d %d", &n, &m);
42         for (int i=0; i<n; i++)
43             for (int j=0; j<m; j++)
44                 scanf ("%d", &Map[i][j]);
45 
46         memset (dp, -1, sizeof(dp));
47         int res = dfs (0, 0, 0);
48 
49         printf ("Case %d: %d\n", ++Case, res);
50     }
51     return 0;
52 }

 

posted @ 2015-06-29 23:56  罗茜  阅读(504)  评论(0编辑  收藏  举报