题目链接:
题目大意:
给出一个矩阵,一个人从左上角走到右下角,一个人从左下角走到右上角,两个人只会在一个点相交,问两个人经过路径上的数的和最大的情况下最大和是多少。
题目分析:
- 可以分别从四个角出发进行动态规划,dp[k][i][j]代表从第k个角出发到达i和j得到的最大的数。
- 枚举每一个点,然后枚举从四个角同时到大这个点的情况,只能是左上角从左侧或上侧到,右下角从右侧或下侧到,其他同理,因为只在所枚举的点相交,所以我们可以认为,左上角如果从左侧进入,因为左小也要到达这个点,所以右下角的点必须从右侧进入。同理,右上角的必须从上侧进入,如果左上角从上侧进入,同理会发现,起始只有一种情况。
- 题目不难,但是要细心,耐心地写。
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAX 1007
using namespace std;
int n,m;
int a[MAX][MAX];
int u,v;
int dp[4][MAX][MAX];
int main ( )
{
while ( ~scanf ( "%d%d" , &n , &m ) )
{
for ( int i = 1 ; i <= n ; i++ )
for ( int j = 1 ; j <= m ; j++ )
scanf ( "%d" , &a[i][j] );
for ( int i = 1 ; i <= n ; i++ )
for ( int j = 1 ; j <= m ; j++ )
{
dp[0][i][j] = 0;
if ( i > 1 )
dp[0][i][j] = max ( dp[0][i-1][j] , dp[0][i][j] );
if ( j > 1 )
dp[0][i][j] = max ( dp[0][i][j-1] , dp[0][i][j] );
dp[0][i][j] += a[i][j];
}
for ( int i = n ; i >= 1 ; i-- )
for ( int j = 1 ; j <= m ; j++ )
{
dp[1][i][j] = 0;
if ( i < n )
dp[1][i][j] = max ( dp[1][i+1][j] , dp[1][i][j] );
if ( j > 1 )
dp[1][i][j] = max ( dp[1][i][j-1] , dp[1][i][j] );
dp[1][i][j] += a[i][j];
}
for ( int i = 1 ; i <= n ; i++ )
for ( int j = m ; j >= 1 ; j-- )
{
dp[2][i][j] = 0;
if ( i > 1 )
dp[2][i][j] = max ( dp[2][i-1][j] , dp[2][i][j] );
if ( j < m )
dp[2][i][j] = max ( dp[2][i][j+1] , dp[2][i][j] );
dp[2][i][j] += a[i][j];
}
for ( int i = n ; i >= 1 ; i-- )
for ( int j = m ; j >= 1 ; j-- )
{
dp[3][i][j] = 0;
if ( i < n )
dp[3][i][j] = max ( dp[3][i+1][j] , dp[3][i][j] );
if ( j < m )
dp[3][i][j] = max ( dp[3][i][j+1] , dp[3][i][j] );
dp[3][i][j] += a[i][j];
}
/*for ( int i = 1 ; i <= n ; i++ )
for ( int j = 1 ; j <= m ; j++ )
{
dp[0][i][j+1] = max ( dp[0][i][j+1] , dp[0][i][j] + a[i][j+1] );
dp[0][i+1][j] = max ( dp[0][i+1][j] , dp[0][i][j] + a[i+1][j] );
}
for ( int i = 1 ; i <= n ; i++ )
for ( int j = m ; j >= 1; j-- )
{
dp[2][i][j-1] = max ( dp[2][i][j-1] , dp[2][i][j] + a[i][j-1] );
dp[2][i+1][j] = max ( dp[2][i+1][j] , dp[2][i][j] + a[i+1][j] );
}
for ( int i = n ; i >= 1 ; i-- )
for ( int j = 1 ; j <= m ; j++ )
{
dp[1][i][j+1] = max ( dp[1][i][j+1] , dp[1][i][j] + a[i][j+1] );
dp[1][i-1][j] = max ( dp[1][i-1][j] , dp[1][i][j] + a[i-1][j] );
}
for ( int i = n ; i >= 1 ; i-- )
for ( int j = n ; j >= 1 ; j-- )
{
dp[3][i][j-1] = max ( dp[3][i][j-1] , dp[3][i][j] + a[i][j-1] );
dp[3][i-1][j] = max ( dp[3][i-1][j] , dp[3][i][j] + a[i-1][j] );
}*/
int ans = 0;
for ( int i = 2; i < n ; i++ )
for ( int j = 2; j < m ; j++ )
{
ans = max ( ans , dp[0][i-1][j]+dp[3][i+1][j]+dp[1][i][j-1]+dp[2][i][j+1] );
ans = max ( ans , dp[0][i][j-1]+dp[3][i][j+1]+dp[1][i+1][j]+dp[2][i-1][j] );
}
printf ( "%d\n" , ans );
}
}