您的位置:首页 > 大数据 > 人工智能

Lightoj 1071 - Baker Vai (双线程DP)

2015-06-29 23:56 435 查看
题目连接:

  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分别代表两者当前所在的行(所在列可以直接求出来)。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int INF = 0x3f3f3f3f;

int Map[maxn][maxn], dp[maxn*2][maxn][maxn];
int n, m;
int dfs (int step, int x, int y)
{
if (step == n + m - 2)
{//走到够了步数
if (x==y && x==n-1 && step-x==m-1)
return Map[n-1][m-1];//刚好到了终点
else
return -INF;//不合法
}
int ans = dp[step][x][y];
if (ans != -1)//前面已经搜过,直接返回
return ans;
if (x<n-1 && y<n-1)//x,y都向下走
ans = max(ans, dfs(step+1, x+1, y+1));
if (x<n-1 && step-y<m-1)//x向下走.y向右走
ans = max(ans, dfs(step+1, x+1, y));
if (step-x<m-1 && y<n-1)//x向右走.y向下走
ans = max(ans, dfs(step+1, x, y+1));
if (step-x<m-1 && step-y<m-1)//x,y都向右走
ans = max(ans, dfs(step+1, x, y));
ans += Map[x][step-x];//选择以上四种情况最优的一种,再加上当前的
if (x != y)//如果相同的话就不加,因为不走重复的一定比走重复的的要大
ans += Map[y][step-y];
dp[step][x][y] = ans;
return ans;

}
int main ()
{
int t, Case = 0;
scanf ("%d", &t);
while (t --)
{
scanf ("%d %d", &n, &m);
for (int i=0; i<n; i++)
for (int j=0; j<m; j++)
scanf ("%d", &Map[i][j]);

memset (dp, -1, sizeof(dp));
int res = dfs (0, 0, 0);

printf ("Case %d: %d\n", ++Case, res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: