Problem:
枠

画像の中から有益な情報を抽出する画像認識はコンピュータサイエンスの中でも重要な研究テーマのひとつです。デジタルカメラ、運転支援システム、防犯システムなどに幅広く応用されています。

このような研究のおかげで、私たちは画像解析を行うための多くのソフトウェアやプログラム集を使い様々な処理を行うことができます。一方、自力でプログラムを書いて解析することで、その仕組みを知り、楽しい時間を過ごすことができます。ここでは、一風変わった画像認識をしてみましょう。

画像として次のような各ピクセルが整数の値を持つ N × N のピクセルが入力として与えられます。この画像の中から、線の太さが１ピクセルの長方形の枠（わく）を１つ抽出します。

枠が覆うピクセルの値の和が最大となるような枠を抽出して、その和を報告するプログラムを作成して
下さい。ただし、下の図のように、縦、横のピクセル数が１つや２つの場合も枠とみなすものとします。

入力

入力は以下の形式で与えられる。

N
p1,1 p1,2 ... p1,N
p2,1 p2,2 ... p2,N
:
pN,1 pN,2 ... pN,N

１行目に縦と横のピクセル数 N (1 ≤ N ≤ 300) が与えられる。続く N 行に、i 行 j 列目のピクセルの値を表す整数 pi,j (-1000 ≤ pi,j ≤ 1000)が与えられる。

出力

ピクセル値の和が最大となるような枠の、ピクセル値の和を１行に出力する。

入出力例

入力例１

5
2 0 0 2 0
0 1 0 2 0
0 0 0 -1 0
0 4 0 3 0
-1 0 0 1 0

出力例１

12

入力例２

3
0 0 0
0 -1 0
0 0 0

出力例２

0

Solution in C++ (judge verdict: Accepted)

#include <iostream>
#include <cstring>
using namespace std;

int main(){
  int n,x[302][302]={},y[302][302]={};
  cin>>n;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)cin>>y[i][j],x[i][j]=y[i][j];
  
  int ans=max(y[0][n-1],y[n-1][0]);
  for(int i=0;i<n;i++)
    for(int j=n-2;j>=0;j--) {
      x[i][j]+=x[i][j+1];
      y[j][i]+=y[j+1][i];
      ans=max(ans,max(y[j][i],x[i][j]));
    }

  int sum[302][302],K[2][302][302]={};
  for(int i=0;i<=n;i++)
    for(int j=0;j<=n;j++) sum[i][j]=-100000000;


  int t=0;
  while(1){
    t++;
    for(int i=0;i<n;i++) //yoko
      for(int j=i+1;j<n;j++) {//yoko
	int a=K[t%2][i][j];
	K[(t+1)%2][i][j]=a;
	sum[i][j]=-100000000;
	for(int k=a+1;k<n;k++) { //tate
	  int X=(x[a][i]-x[a][j+1])+(x[k][i]-x[k][j+1]);
	  int Y=(y[a+1][i]-y[k][i])+(y[a+1][j]-y[k][j]);
	  if(sum[i][j]<=X+Y)sum[i][j]=X+Y,K[(t+1)%2][i][j]=k;
	  ans=max(ans,sum[i][j]);
	}
      }

    int f=1;
    for(int i=0;i<n;i++) //yoko
      for(int j=i+1;j<n;j++) //yoko
	for(int k=K[t%2][i][j]+1;k<K[(t+1)%2][i][j];k++){
	  f=0;
	  int X=(x[k][i+1]-x[k][j])-(x[k-1][i]-x[k-1][j+1]);
	  sum[i][j]+=X;
	  ans=max(ans,sum[i][j]);
	}
    if(f)break;
  }
  cout <<ans<<endl;
	  
  return 0; 
}