Codeforces Round #245 (Div. 1) -- B. Working out (DP)

来源:互联网 发布:做布料软件 编辑:程序博客网 时间:2024/06/05 05:49

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 mcolumns. 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] ora[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 eithera[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 elementa[i][j] (0 ≤ a[i][j] ≤ 105).

Output

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

Example
Input
3 3100 100 100100 1 100100 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].


题意:感觉说的很模糊,要求两个人只能相遇一次,竟然是两个人的路线只能有一个交点,后来发现坑点原来是 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.。这句话解释了,是真的坑啊。

思路: 他们都说是四角dp,确实很形象,动态转移方程很好推导,比较难的就是从怎么走,怎么理解路线。

由他们的行走方式可知,对于同一个人是不会走相同的点两次的(为什么可以根据那个人的行走方式画一下图),

还有就是他们相遇的地点不会在边界上,不然他们路线的交点至少有两个(感觉不可思议也可以画一下图)。

然后就是怎么处理"走了"。

先预处理出从四个顶点出发到任一点的最大值,用dp即可。然后 枚举相遇点,相遇点不可能在边缘,因为那样交点就肯定不止一个,对于每个交点有两种方式走。

特别说明一下,:因为是不走已经工作过的点,所以走相遇点只有两种方式,第一个人横着走过去,第二个人竖着走

过去,或者反过来!第一个人竖着走过去,第二个人横着走过去!


上代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;int ap[1010][1010];int dp1[1010][1010];int dp2[1010][1010];int dp3[1010][1010];int dp4[1010][1010];int main(){int n,m;scanf("%d %d",&n,&m);for(int i=1; i<=n; i++)   for(int j=1; j<=m; j++)    scanf("%d",&ap[i][j]);dp1[1][1] = ap[1][1]; dp1[1][0]=dp1[0][1] = 0;    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]) + ap[i][j];dp2[n][1] = ap[n][1]; dp2[n][0] = dp2[n+1][1] = 0;for(int i=n; i>=1; i--) for(int j=1; j<=m; j++)  dp2[i][j] = max(dp2[i][j-1],dp2[i+1][j]) + ap[i][j];  dp3[n][m] = ap[n][m]; dp3[n][m+1] = dp3[n+1][m] = 0;for(int i=n; i>=1; i--)  for(int j=m; j>=1; j--)    dp3[i][j] = max(dp3[i][j+1], dp3[i+1][j]) + ap[i][j];dp4[1][m] = ap[1][m]; dp4[0][m] = dp4[1][m+1] = 0;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]) + ap[i][j];int maxn = 0;for(int i=2; i<=n-1; i++)  for(int j=2; j<=m-1; j++) { maxn = max(maxn, dp1[i][j-1] + dp2[i+1][j] + dp3[i][j+1] + dp4[i-1][j]); maxn = max(maxn, dp1[i-1][j] + dp2[i][j-1] + dp3[i+1][j] + dp4[i][j+1]); } cout << maxn << endl;return 0;}


水波




原创粉丝点击