Problem:
Max Score: $600$ Points

Problem Statement

Sigma and his brother Sugim are in the $H \times W$ grid. They wants to buy some souvenirs.

Their start position is upper-left cell, and the goal position is lower-right cell.

Some cells has a souvenir shop. At $i$-th row and $j$-th column, there is $a_{i, j}$ souvenirs.

In one move, they can go left, right, down, and up cell.

But they have little time, so they can move only $H+W-2$ times.

They wanted to buy souvenirs as many as possible, but they had no computer, so they couldn't get the maximal numbers of souvenirs.

Write a program and calculate the maximum souvenirs they can get, and help them.

Input

The input is given from standard input in the following format.

$H \ W$
$a_{1, 1} \ a_{1, 2} \ \cdots \ a_{1, W}$
$a_{2, 1} \ a_{2, 2} \ \cdots \ a_{2, W}$
$\vdots \ \ \ \ \ \ \ \ \ \ \vdots \ \ \ \ \ \ \ \ \ \ \vdots$
$a_{H, 1} \ a_{H, 2} \ \cdots \ a_{H, W}$

Output

Print the maximum number of souvenirs they can get.

Constraints

$1 \le H, W \le 200$

$0 \le a_{i, j} \le 10^5$

Subtasks

Subtask 1 [ 50 points ]

The testcase in the subtask satisfies $1 \le H \le 2$.

Subtask 2 [ 80 points ]

The testcase in the subtask satisfies $1 \le H \le 3$.

Subtask 3 [ 120 points ]

The testcase in the subtask satisfies $1 \le H, W \le 7$.

Subtask 4 [ 150 points ]

The testcase in the subtask satisfies $1 \le H, W \le 30$.

Subtask 5 [ 200 points ]

There are no additional constraints.

Sample Input 1

3 3
1 0 5
2 2 3
4 2 4

Sample Output 1

21

The cell at $i$-th row and $j$-th column is denoted $(i, j)$.

In this case, one of the optimal solution is this:

Sigma moves $(1, 1) -> (1, 2) -> (1, 3) -> (2, 3) -> (3, 3)$.

Sugim moves $(1, 1) -> (2, 1) -> (3, 1) -> (3, 2) -> (3, 3)$.

Then, they can get $21$ souvernirs.

Sample Input 2

6 6
1 2 3 4 5 6
8 6 9 1 2 0
3 1 4 1 5 9
2 6 5 3 5 8
1 4 1 4 2 1
2 7 1 8 2 8

Sample Output 2

97

Writer : square1001

Solution in C (GCC 5.4.1) (judge verdict: Accepted)

#include<stdio.h>

int map[200][200],dp[200][200][400];
int h,w;

int search(int ax,int ay,int bx,int by){
  int i,c,max=0;
  if(ax==0 && ay==0){
    return map[0][0]+search(ax+1,ay,bx,by+1);
  }else if(ax==h-1 && ay==w-1){
    return map[h-1][w-1];
  }else{
    if(dp[ax][bx][ax+ay]==0){
    for(i=0;i<4;i++){
      if(ax+(i%2)<h && ay+(1-i%2)<w && bx+i/2<h && by+(1-i/2)<w){
        if((ax+(i%2)!=bx+(i/2)) || ax+ay==w+h-3){
        c=map[ax][ay]+map[bx][by]+search(ax+(i%2),ay+(1-i%2),bx+i/2,by+(1-i/2));
        if(c>max) max=c;
        }
      }
    }
    return dp[ax][bx][ax+ay]=max;
    }else{
      return dp[ax][bx][ax+ay];
    }
  }
}

int main(){
  int i,j,k;
  scanf("%d %d",&h,&w);
  for(i=0;i<h;i++){
    for(j=0;j<w;j++){
      scanf("%d",&map[i][j]);
      for (k = 0; k < h+w; k++) {
        dp[i][j][k]=0;
        }
    }
  }
  printf("%d\n",search(0,0,0,0));
  return 0;
}