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
28 46 80
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <string> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define INT_INF 0x3fffffff #define LL_INF 0x3fffffffffffffff #define EPS 1e-12 #define MOD 1000000007 #define PI 3.141592653579798 #define N 2000 #define E 100000 using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef double DB; struct Edge { int st,en,cap,flow,cost,next; } edge[E]; int head[N] , tot , now[N]; int source,sink; int pre[N] , dis[N]; queue<int> q; bool vs[N]; void add_edge(int st,int en,int cap,int cost) { edge[tot].st=st; edge[tot].en=en; edge[tot].cap=cap; edge[tot].flow=0; edge[tot].cost=cost; edge[tot].next=head[st]; head[st]=tot++; edge[tot].st=en; edge[tot].en=st; edge[tot].cap=0; edge[tot].flow=0; edge[tot].cost=-cost; edge[tot].next=head[en]; head[en]=tot++; } bool SPFA() { for(int i=0; i<N; i++) dis[i]=-1; memset(vs,0,sizeof(vs)); memset(now,-1,sizeof(now)); while(!q.empty()) q.pop(); q.push(source); dis[source]=0; vs[source]=1; while(!q.empty()) { int u=q.front(); q.pop(); vs[u]=0; for(int i=head[u],v; i!=-1; i=edge[i].next) if(edge[i].cap-edge[i].flow>0 && dis[v=edge[i].en]<dis[u]+edge[i].cost) { dis[v]=dis[u]+edge[i].cost; now[v]=i; if(!vs[v]) { vs[v]=1; q.push(v); } } } if(dis[sink]!=-1) return true; else return false; } int MCMF() { int cost=0; while(SPFA()) { int flow=INT_INF; for(int u=sink; u!=source; u=edge[now[u]].st) if(flow>edge[now[u]].cap-edge[now[u]].flow) flow=edge[now[u]].cap-edge[now[u]].flow; for(int u=sink; u!=source; u=edge[now[u]].st) { edge[now[u]].flow+=flow; edge[now[u]^1].flow-=flow; } cost+=flow*dis[sink]; } return cost; } void build(int n) { memset(head,-1,sizeof(head)); tot=0; source=N-2; sink=N-1; for(int i=0; i<n; i++) for(int j=0,val,p1,p2; j<n; j++) { p1=i*n+j; p2=p1+n*n; scanf("%d",&val); add_edge(p1,p2,1,val); if(p1==0 || p1==n*n-1) add_edge(p1,p2,INT_INF,0); if(i+1<n) add_edge(p2,(i+1)*n+j,1,0); if(j+1<n) add_edge(p2,i*n+j+1,1,0); } add_edge(source,0,2,0); add_edge(n*n-1+n*n,sink,2,0); } int main() { int n; while(scanf("%d",&n)!=EOF) { build(n); int ans=MCMF(); printf("%d\n",ans); } return 0; }