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 }
本文为博主原创文章,未经博主允许不得转载。