[dp] Codeforces 429B B. Working out(动态规划(DP))

来源:互联网 发布:单片机温度计原理图 编辑:程序博客网 时间:2024/05/20 04:31
作者:Accagain

链接:点击打开链接

原题

B. Working out

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output

Summer is coming! It's time for Iahub and Iahubina to work out, as they both want to look hot at the beach. The gym where they go is a matrix a with n lines and m columns. Let number a[i][j] represents the calories burned by performing workout at the cell of gym in the i-th line and the j-th column.

Iahub starts with workout located at line 1 and column 1. He needs to finish with workout a[n][m]. After finishing workout a[i][j], he can go to workout a[i + 1][j] or a[i][j + 1]. Similarly, Iahubina starts with workout a[n][1] and she needs to finish with workout a[1][m]. After finishing workout from cell a[i][j], she goes to either a[i][j + 1] or a[i - 1][j].

There is one additional condition for their training. They have to meet in exactly one cell of gym. At that cell, none of them will work out. They will talk about fast exponentiation (pretty odd small talk) and then both of them will move to the next workout.

If a workout was done by either Iahub or Iahubina, it counts as total gain. Please plan a workout for Iahub and Iahubina such as total gain to be as big as possible. Note, that Iahub and Iahubina can perform workouts with different speed, so the number of cells that they use to reach meet cell may differs.

Input

The first line of the input contains two integers n and m (3 ≤ n, m ≤ 1000). Each of the next n lines contains m integers: j-th number from i-th line denotes element a[i][j] (0 ≤ a[i][j] ≤ 105).

Output

The output contains a single number — the maximum total gain possible.

Examples
input

3 3
100 100 100
100 1 100
100 100 100

output

800

Note

Iahub will choose exercises a[1][1] → a[1][2] → a[2][2] → a[3][2] → a[3][3]. Iahubina will choose exercises a[3][1] → a[2][1] → a[2][2] → a[2][3] → a[1][3].


题意


给n*m的矩阵,每个格子有个数,A从(1,1)出发只能向下或右走,终点为(n,m),B从(n,1)出发只能向上或右走,终点为(1,m)。两个人的速度不一样,走到的格子可以获的该格子的数,两人相遇的格子上的数两个人都不能拿。求A和B能拿到的数的总和的最大值。


涉及知识及算法

动态规划
先计算出每个格子到四个角落格子的路径最大数值,然后枚举两个人相遇的交点格子,从交点格子到四个角落的路径之和即为题目要求的总和。不过要注意的是,有两种方式汇于交点,画出来大概像佛教“万”字卍和法西斯(纳粹)符号“卐“,求总和的最大值即可。需要注意边界情况。

代码

#include<iostream>#include<cmath>#include<cstdio>#include<sstream>#include<cstdlib>#include<string>#include<string.h>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#include<bitset>#include<cmath>#define eps 1e-6#define INF 0x3f3f3f3f#define PI acos(-1.0)#define ll __int64#define LL long long#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#define M 1000000007//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define Maxn 1100ll dp[5][Maxn][Maxn];int n,m;ll save[Maxn][Maxn];int main(){   //freopen("in.txt","r",stdin);   //freopen("out.txt","w",stdout);   while(~scanf("%d%d",&n,&m))   {       memset(save,0,sizeof(save));       for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                scanf("%d",&save[i][j]);       memset(dp,0,sizeof(dp));       for(int i=1;i<=n;i++)       {           //从左上角           for(int j=1;j<=m;j++)               dp[1][i][j]=max(dp[1][i-1][j],dp[1][i][j-1])+save[i][j];               //printf("i:%d j:%d %I64d\n",i,j,dp[1][i][j]);           //从右上角           for(int j=m;j>=1;j--)                dp[3][i][j]=max(dp[3][i-1][j],dp[3][i][j+1])+save[i][j];       }       for(int i=n;i>=1;i--)       {           //从左下角           for(int j=1;j<=m;j++)                dp[2][i][j]=max(dp[2][i+1][j],dp[2][i][j-1])+save[i][j];           //从右下角           for(int j=m;j>=1;j--)                dp[4][i][j]=max(dp[4][i+1][j],dp[4][i][j+1])+save[i][j];       }       ll ans=0;       //把四个边界都置为无效情况       for(int i=0;i<=n+1;i++)              for(int k=1;k<=4;k++)                dp[k][i][0]=dp[k][i][m+1]=-INF;       for(int j=0;j<=m+1;j++)            for(int k=1;k<=4;k++)                dp[k][0][j]=dp[k][n+1][j]=-INF;       for(int i=1;i<=n;i++)       {           for(int j=1;j<=m;j++)           {                   //只用考虑两种情况 两个人只能交叉一个格子,多了的话不合算               //卐形               ll temp=dp[1][i][j-1]+dp[4][i][j+1]+dp[2][i+1][j]+dp[3][i-1][j];               ans=max(ans,temp);               //卍形               temp=dp[1][i-1][j]+dp[4][i+1][j]+dp[2][i][j-1]+dp[3][i][j+1];               ans=max(ans,temp);               //printf("i:%d j:%d %I64d\n",i,j,ans);           }       }       printf("%I64d\n",ans);   }   return 0;}



原创粉丝点击