题目大意:给定一张网格图,起始点为(1,1),终点为(n,m),需要来回走两次,但是只允许起点终点是一样的,其余都不可以,问最多可以帮助多少个人;
题目解析:我们可以转化一下,转化成两个人,一个人从(1,2)出发走向(n-1,m),另一个人从(2,1)出发,走向(n,m-1);假设他们两个人在途中某一点(x,y)相遇了,那么他们两个到达这个点所经过的时间一定相同,所以要保证两个人始终不会相遇,只需保证在每个时间点他们两个人都不相遇即可;定义dp[i][j][k]表示在i这个时间点,第一个人的x坐标为j,第二个人的x坐标为k,到达目标位置能获取的最大权值,dp的时候记忆化搜索就ok了;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int dp[201][101][101],graph[107][107],n,m;
const int inf=0x3fffffff;
int dfs(int pos,int x1,int x2)
{
if(dp[pos][x1][x2]!=-1) return dp[pos][x1][x2];
int y1=pos-x1,y2=pos-x2;
if(x1>n||y1>m||x2>n||y2>m||(x1==x2&&y1==y2)) return -1;
int ans=graph[x1][y1]+graph[x2][y2];
if(x1==n&&y1==m-1&&x2==n-1&&y2==m)
{
return ans;
}
int temp=0;
if(dfs(pos+1,x1,x2)!=-1)
temp=max(temp,dfs(pos+1,x1,x2));
if(dfs(pos+1,x1+1,x2)!=-1)
temp=max(temp,dfs(pos+1,x1+1,x2));
if(dfs(pos+1,x1,x2+1)!=-1)
temp=max(temp,dfs(pos+1,x1,x2+1));
if(dfs(pos+1,x1+1,x2+1)!=-1)
temp=max(temp,dfs(pos+1,x1+1,x2+1));
ans+=temp;
return dp[pos][x1][x2]=ans;
}
int solve()
{
memset(dp,-1,sizeof(dp));
return dfs(3,2,1)+graph[1][1]+graph[n][m];
}
int main()
{
int cas,c,i,j;
scanf("%d",&cas);
for(c=1;c<=cas;c++)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&graph[i][j]);
}
}
printf("Case %d: %d\n",c,solve());
}
return 0;
}