首先最优解一定可以是左上的一片区域海拔为0,右下的一片区域海拔为1
证明的话,如果有很多小数的话,对于一个海拔为小数的格子,他的海拔变成相邻的格子中的一个的海拔,一定不比原来劣,那么对于海拔相同的,连在一起的格子视为一个块,这个块的海拔若是小数,他仍然可以按上文的方式合并到其他块,最后只剩一块0和一块1(为什么0和1不能合并?能合并当然好但是题目规定了两个点的海拔)
然后花费就来自于0和1的分界线,那么就变成了最小割了
然后因为很慢跑不过去
观察到这是一个平面图,将它转成对偶图,原图的最小割对应对偶图的最短路,就可以了
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9+10
using namespace std;
inline void read(int &x)
{
char c;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxn = 260000;
const int maxm = maxn*4;
int n,m,st,ed;
struct edge
{
int y,c,nex;
}a[maxm]; int len,fir[maxn];
void ins(const int x,const int y,const int c)
{
a[++len].y=y; a[len].c=c;
a[len].nex=fir[x]; fir[x]=len;
}
struct node
{
int x,i;
node(){}
node(const int &_x,const int &_i){x=_x;i=_i;}
};
inline bool operator <(node x,node y){return x.x>y.x;}
priority_queue<node>q;
int d[maxn];
void search()
{
for(int i=0;i<=ed;i++) d[i]=inf;
d[st]=0; q.push(node(0,st));
while(!q.empty())
{
node x=q.top(); q.pop();
if(x.x!=d[x.i]) continue;
for(int k=fir[x.i];k;k=a[k].nex)
{
const int y=a[k].y;
if(d[y]>x.x+a[k].c)
{
d[y]=x.x+a[k].c;
q.push(node(d[y],y));
}
}
}
}
int main()
{
len=0; memset(fir,0,sizeof fir);
read(n); st=n*n+1,ed=st+1;
for(int i=1,id=1;i<=n+1;i++)
for(int j=1;j<=n;j++,id++)
{
int x; read(x);
if(i==1) ins(id,ed,x);
else if(i==n+1) ins(st,id-n,x);
else ins(id,id-n,x);
}
for(int i=1,id=1;i<=n;i++)
for(int j=1;j<=n+1;j++,id++)
{
int x; read(x);
if(j==1) ins(st,id,x);
else if(j==n+1) ins(--id,ed,x);
else ins(id-1,id,x);
}
for(int i=1,id=1;i<=n+1;i++)
for(int j=1;j<=n;j++,id++)
{
int x; read(x);
if(i==1) continue;
else if(i==n+1) continue;
else ins(id-n,id,x);
}
for(int i=1,id=1;i<=n;i++)
for(int j=1;j<=n+1;j++,id++)
{
int x; read(x);
if(j==1) continue;
else if(j==n+1) id--;
else ins(id,id-1,x);
}
search();
printf("%d\n",d[ed]);
return 0;
}