看到题目,没什么思路
看了大佬博客:https://blog.csdn.net/xiaolonggezte/article/details/69145427,豁然开朗,还是有些小问题没注意,wa了挺久
题意:
在n*m的格子里,A从(1,1)到(n,m),B从(n,1)到(1,m),
A只能从 (i, j) 到 (i+1 , j) 或者 (i, j+1),B只能从 (i, j) 到 (i-1, j) 或者 (i, j+1)
A和B的路线有且只有一点重合,并且这一点不在A和B的起点或终点,
求怎样走使A和B的路线的权值之和(重合点的权值不计算)最大
思路:
把路线分成四段,设重合点为x,计算 (1,1)到x,(n,m)到x,(1,m)到x,(n,1)到x 四段路的权值和;
注意:
重合的点不在边界,并且只有一个点重合!
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll dp1[1100][1100],dp2[1100][1100],dp3[1100][1100],dp4[1100][1100];
//重合的点为x,dp1:(1,1)到x,dp2:(n,m)到x,dp3:(n,1)到x,dp4: (1,m)到x
ll a[1100][1100];
int main()
{
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
memset(dp3,0,sizeof(dp3));
memset(dp4,0,sizeof(dp4));
int n,m;
cin>>n>>m;
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++)
cin>>a[i][j];
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++)
dp1[i][j] = max(dp1[i-1][j],dp1[i][j-1])+a[i][j];
for(int i = n;i > 0;i--)
for(int j = m;j > 0;j--)
dp2[i][j] = max(dp2[i+1][j],dp2[i][j+1])+a[i][j];
for(int i = n;i > 0;i--)
for(int j = 1;j <= m;j++)
dp3[i][j] = max(dp3[i+1][j],dp3[i][j-1])+a[i][j];
for(int i = 1;i <= n;i++)
for(int j = m;j > 0;j--)
dp4[i][j] = max(dp4[i-1][j],dp4[i][j+1])+a[i][j];
ll ans = 0;
//注意(i,j)不在边界
for(int i = 2; i < n; i ++)
for(int j = 2; j < m; j ++)
{
//除了(i,j)外的点不能再重合,所以一共就两种走法 ,没考虑路径,直接用和-4*a[i][j],wa疯
ans = max(ans,dp1[i - 1][j] + dp2[i + 1][j]+dp3[i][j - 1] + dp4[i][j + 1]);
ans = max(ans,dp1[i][j - 1] + dp2[i][j + 1] + dp3[i + 1][j] + dp4[i - 1][j]);
}
cout<<ans<<endl;
return 0;
}