Yifenfei very like play a number game in the n*n Matrix. A positive integer number is put in each area of the Matrix.
Every time yifenfei should to do is that choose a detour which frome the top left point to the bottom right point and than back to the top left point with the maximal values of sum integers that area of Matrix yifenfei choose. But from the top to the bottom can only choose right and down, from the bottom to the top can only choose left and up. And yifenfei can not pass the same area of the Matrix except the start and end.
Input
The input contains multiple test cases.
Each case first line given the integer n (2 < n < 30)
Than n lines,each line include n positive integers.(<100)
Output
For each test case output the maximal values yifenfei can get.
Sample Input
2
10 3
5 10
3
10 3 3
2 5 3
6 7 10
5
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
Sample Output
28
46
80
Although we are talking about running forward and backward twice, in fact, we can think that there are only two streams from the beginning to the end.
Looking at the mention that each point can only walk once, I think of the dismantling point network flow, and because it is with some weight, it is the maximum cost flow.
The map I built
... Left point... Right point.
S—[2,0]—-1 —–[2,cost]— n*n+1
……………….2——[1,cost]—n*n+2
……………….3——[1,cost]—n*n+3
……………..n*n—–[2,cost]—n*n+n*n —[2,0]——T
The left point is the entry point and the right point is the exit point. This kind of disassembly is very common and easy to understand.
HDU 2686 and 4322 are the same, so we changed the scope below.
Code
#include<bits/stdc++.h>
using namespace std ;
typedef long long LL ;
#define debug() puts("======")
const int MAXN = 5*(30+10)*(30+10)+100;
const int MAXM = 1e5+100 ;
const int mod = 1e9+7 ;
const int inf = 0x3f3f3f3f;
struct Edge {
int to,cap,flow,cost,next;
}edge[MAXM];
int head[MAXN],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b,int w,int c){
edge[top].to=b;edge[top].cap=w;edge[top].flow=0;edge[top].cost=c;edge[top].next=head[a];
head[a]=top++;
edge[top].to=a;edge[top].cap=0;edge[top].flow=0;edge[top].cost=-c;edge[top].next=head[b];
head[b]=top++;
}
int n;
int S,T;
int a,b;
void getmap(){ // Map building
S=0; T=2*n*n+1;
int temp=n*n;
addedge(S,1,2,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int val;scanf("%d",&val);
if(i==1&&j==1){
a=val;
addedge((i-1)*n+j,(i-1)*n+j+temp,2,val);
int nx=i+1;int ny=j;
if(nx>=1&&nx<=n&&ny>=1&&ny<=n)
addedge((i-1)*n+j+temp,(nx-1)*n+ny,1,0);
nx=i; ny=j+1;
if(nx>=1&&nx<=n&&ny>=1&&ny<=n)
addedge((i-1)*n+j+temp,(nx-1)*n+ny,1,0);
continue;
}
if(i==n&&j==n) {
b=val;
addedge((i-1)*n+j,(i-1)*n+j+temp,2,val);
addedge((i-1)*n+j+temp,T,2,0);
continue;
}
addedge((i-1)*n+j,(i-1)*n+j+temp,1,val);
int nx=i+1;int ny=j;
if(nx>=1&&nx<=n&&ny>=1&&ny<=n)
addedge((i-1)*n+j+temp,(nx-1)*n+ny,1,0);
nx=i; ny=j+1;
if(nx>=1&&nx<=n&&ny>=1&&ny<=n)
addedge((i-1)*n+j+temp,(nx-1)*n+ny,1,0);
}
}
}
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
bool spfa(int s,int t){
queue<int>Q;
memset(dis,-inf,sizeof(dis));
memset(vis,false,sizeof(vis));
memset(pre,-1,sizeof(pre));
dis[s]=0;vis[s]=true;Q.push(s);
while(!Q.empty()){
int now=Q.front();Q.pop();vis[now]=0;
for(int i=head[now];i!=-1;i=edge[i].next){
Edge e=edge[i];
if(e.cap>e.flow&&dis[e.to]<dis[now]+e.cost){
dis[e.to]=dis[now]+e.cost;
pre[e.to]=i;
if(!vis[e.to]){
vis[e.to]=true;
Q.push(e.to);
}
}
}
}
return pre[t]!=-1;
}
void MCMF(int s, int t, int &flow, int &cost)
{
cost = flow = 0;
while(spfa(s, t)) {
int Min = inf;
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]){
Edge E = edge[i];
Min = min(Min, E.cap-E.flow);
}
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
edge[i].flow += Min;
edge[i^1].flow -= Min;
cost += edge[i].cost * Min;
}
flow += Min;
}
}
int main(){
while(scanf("%d",&n)!=EOF){
init();
getmap();
int flow,ans;
MCMF(S,T,flow,ans);
printf("%d\n",ans-a-b);//The last thing I did was to go to the starting point one more time.
}
return 0;
}