CodeForces 429B(四角递推+枚举)

题目大意:给定一个能n×m的表格,每个点上有相应的权值,一个人从(1,1)点出发,目标点为(n,m),另一个人从(n,1)点出发,目标点为(1,m),两个人在行走的过程中只能在一个点相遇,求除去这个点之外,他们所经过的点的权值的最大值

分析:通过简单分析,我们可以将题目转化为从四个角出发,到相遇节点的各自的最大值相加,各个角到相遇节点的最大值可以通过递推公式来求出,而题目中又要求必须仅有一个点相遇,那也就是说除去这个点之外,其他的点只能允许一个人通过,那么我们可以根据分析可知,两个人经过相遇节点只能有两种途径:

假设相遇节点为(i,j)

  • 1、从(1,1)点出发的人由(i-1,j)到达(i,j),并且只能从(i+1,j)走出,从(n,1)点出发的人由(i,j-1)到达(i,j),并只能从(i,j+1)走出去
  • 2、从(1,1)点出发的人由(i,j-1)到达(i,j),并且只能从(i,j+1)走出,从(n,1)点出发的人由(i+1,j)到达(i,j),并只能从(i-1,j)走出去

除去上述两种方法之外,可能还有同学认为两人可以分别从(i+1,j),(i-1,j)进入(i,j),如果这样的化,那么他们的下一步一定会经过另一个人走过的路,而这个与题目的要求不符合

通过上述的分析,我们可以得到下面的表达式:

res = max(res,dp1[i-1][j]+dp2[i+1][j]+dp3[i][j-1]+dp4[i][j+1]); 对应的上面的第一种情况
res = max(res,dp1[i][j-1]+dp2[i][j+1]+dp3[i+1][j]+dp4[i-1][j]); 对应的上面的第二种情况

上述表达式中的dp[i][j]表示的是从相应的角出发到(i,j)节点的最大值

还有一点必须要注意:相遇的节点肯定不是边缘上的点,因为在边缘相遇,下一步肯定会重合

AC代码

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAXN = 1005;
int n,m;
int dp1[MAXN][MAXN],dp2[MAXN][MAXN],dp3[MAXN][MAXN],dp4[MAXN][MAXN];
int arr[MAXN][MAXN];

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				scanf("%d",&arr[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]) + arr[i][j];
		for(int i=n;i>=1;--i)
			for(int j=m;j>=1;--j)
				dp2[i][j] = max(dp2[i][j+1],dp2[i+1][j]) + arr[i][j];
		for(int i=n;i>=1;--i)
			for(int j=1;j<=m;++j)
				dp3[i][j] = max(dp3[i][j-1],dp3[i+1][j]) + arr[i][j];
		for(int i=1;i<=n;++i)
			for(int j=m;j>=1;--j)
				dp4[i][j] = max(dp4[i-1][j],dp4[i][j+1]) + arr[i][j];
		int res = 0;
		for(int i=2;i<n;++i)
			for(int j=2;j<m;++j)
			{
				res = max(res,dp1[i-1][j]+dp2[i+1][j]+dp3[i][j-1]+dp4[i][j+1]);
				res = max(res,dp1[i][j-1]+dp2[i][j+1]+dp3[i+1][j]+dp4[i-1][j]);
			}
		printf("%d\n",res);
	}
	return 0;
}
发布了33 篇原创文章 · 获赞 2 · 访问量 1722

猜你喜欢

转载自blog.csdn.net/weixin_42469716/article/details/103000928
今日推荐