#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <cctype> #include <vector> #include <stack> #include <queue> #include <map> #include <algorithm> #include <iostream> #include <string> #include <set> #define X first #define Y second #define sqr(x) (x)*(x) #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; const double PI = acos(-1.0); map<int, int>::iterator it; typedef long long LL ; template<typename T> void checkmin(T &x, T y) {x = min(x, y);} template<typename T> void checkmax(T &x, T y) {x = max(x, y);} const LL inf = 1LL << 56; const int N = 360006 * 2; const int M = N * 5; struct Edge { int st, en, next; LL flow, cost, cap; } E[M]; int head[N] , nedge , now[N], node; int src, dest, pre[N]; LL dis[N]; queue<int> q; bool vs[N]; void add_edge(int st, int en, LL cap, LL cost) { E[nedge].st = st; E[nedge].en = en; E[nedge].cap = cap; E[nedge].flow = 0; E[nedge].cost = cost; E[nedge].next = head[st]; head[st] = nedge++; E[nedge].st = en; E[nedge].en = st; E[nedge].cap = 0; E[nedge].flow = 0; E[nedge].cost = -cost; E[nedge].next = head[en]; head[en] = nedge++; } bool SPFA() { for(int i = 0; i < node; i++) dis[i] = inf; memset(vs, 0, sizeof(vs)); memset(now, -1, sizeof(now)); while(!q.empty()) q.pop(); q.push(src); dis[src] = 0; vs[src] = 1; while(!q.empty()) { int u = q.front(); q.pop(); vs[u] = 0; for(int i = head[u], v; i != -1; i = E[i].next) if(E[i].cap - E[i].flow > 0 && dis[v=E[i].en] > dis[u] + E[i].cost) { dis[v] = dis[u] + E[i].cost; now[v] = i; if(!vs[v]) { vs[v] = 1; q.push(v); } } } if(dis[dest] != inf) return true; else return false; } void MCMF(LL &flow, LL &cost) { cost = 0, flow = 0; while(SPFA()) { LL fw = inf; for(int u = dest; u != src; u = E[now[u]].st) if(fw > E[now[u]].cap - E[now[u]].flow) fw = E[now[u]].cap - E[now[u]].flow; for(int u = dest; u != src; u = E[now[u]].st) { E[now[u]].flow += fw; E[now[u] ^ 1].flow -= fw; } flow += fw; cost += fw * dis[dest]; } } void init(int _node, int _src, int _dest) { nedge = 0; node = _node; src = _src; dest = _dest; for(int i = 0; i < node; i++)head[i] = -1; } const int SN = 606; int a[SN][SN]; int main() { int n; while(~scanf("%d", &n)) { int m = n * n; init(2 * m + 2 , 0, 2 * m - 1); for(int i = 0; i < n; ++i) { for(int j = 0; j < n; ++j) { scanf("%d", &a[i][j]); int id = i * n + j; int cap = 1; if(i == 0 && j == 0 || i == n - 1 && j == n - 1)cap = 2; add_edge(id, id + m, cap, -a[i][j]); if(i < n - 1)add_edge(id + m, id + n , 1, 0); if(j < n - 1)add_edge(id + m, id + 1, 1, 0); } } LL res = 0, cost = 0, flow = 0; MCMF(flow, cost); res += -(cost+a[0][0]+a[n-1][n-1]); //printf("cost = %I64d flow = %I64d ", cost, flow); printf("%I64d ", res); } return 0; }