codeforces 429B B. Working out 详解(dp)

来源:互联网 发布:数据交换平台建设方案 编辑:程序博客网 时间:2024/05/17 04:47
D. Working out
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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 matrixa with n lines andm columns. Let number a[i][j] represents the calories burned by performing workout at the cell of gym in thei-th line and the j-th column.

Iahub starts with workout located at line 1 and column1. 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 workouta[n][1] and she needs to finish with workouta[1][m]. After finishing workout from cella[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 andm (3 ≤ n, m ≤ 1000). Each of the nextn 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.

Examples
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 exercisesa[3][1] → a[2][1] → a[2][2] → a[2][3] → a[1][3].


题目大意:

一个人从左上走到右下,一个人从左下走到右上,两个人必须有一个点作为见面点,见面点的权值不能拿,问按照规则走,取得最大权值的和为多少。

思路:

首先要保证只有一个格子重合,那么只可能是以下两种情况: 
1) A向右走,相遇后继续向右走,而B向上走,相遇后继续向上走 
2) A向下走,相遇后继续向下走,而B向右走,相遇后继续向右走

接着枚举相遇的格子(i,j)即可,考虑四个方向的dp

dp1[i][j] := 从 (1, 1) 到 (i, j) 的最大分数  注意:这里的dp[i][j]只能从左面或者上面来 
dp2[i][j] := 从 (i, j) 到 (n, m) 的最大分数  注意:这里是从dp[i][j]往mn去,所以他的去向是右面跟下面,看代码就理解了
dp3[i][j] := 从 (n, 1) 到 (i, j) 的最大分数 
dp4[i][j] := 从 (i, j) 到 (1, m) 的最大分数


这种题一看就是递推dp,但是唯一定点卡主了,还是不够老道,完全可以枚举每个点,将复杂问题变小

#include<bits/stdc++.h>using namespace std;const int maxn = 1e3+5;int dp1[maxn][maxn], dp2[maxn][maxn], dp3[maxn][maxn], dp4[maxn][maxn], a[maxn][maxn];int main(){    int n, m;    while(~scanf("%d%d",&n, &m))    {        memset(dp1, 0, sizeof(dp1));        memset(dp2, 0, sizeof(dp2));        memset(dp3, 0, sizeof(dp3));        memset(dp4, 0, sizeof(dp4));        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++)            dp1[i][j] = max(dp1[i-1][j], dp1[i][j-1]) + a[i][j];  //只能往右还有往下走,也就是来源就是左面跟上面        for(int i = n; i >= 1; i--) // 右下            for(int j = m; j >= 1; j--)            dp2[i][j] = max(dp2[i+1][j], dp2[i][j+1]) + a[i][j];//从ij到mn,也就是去往他的右面跟下面        for(int i = n; i >= 1; 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 >= 1; j--)            dp4[i][j] = max(dp4[i-1][j], dp4[i][j+1]) + a[i][j];        int ans = 0;        for(int i = 2; i < n; i++)            for(int j = 2; j < m; j++)        {            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;}


0 0
原创粉丝点击