首先进行贪心,发现海拔有梯度时一定是不优的,最优的情况是海拔像断崖一样上升,也就是左上角有一片海拔高度为\(0\),右下角有一片海拔高度为\(1\)。

发现这样的性质后,不难想到用最小割来解决问题,但数据规模过大,需要进行优化。

考虑到网格图是特殊的平面图,那么我们就将平面图转化为对偶图,通过对偶图求最短路来求平面图的最小割。

下面分析如何转化为对偶图:

我的做法是先\(n++\),使\(n×n\)个区域转化为\(n×n\)个点。

一个区域用其左上角点的坐标来表示。(图中的红点)

平面图中的有向边顺时针旋转\(90°\)后作为对偶图中的边,例如当原图的有向边为自西向东(从左到右)时,连边情况应为:

黄色箭头表示原平面图中的边,蓝色箭头表示对偶图中的边,其他三种情况同理。

建完对偶图后,从\(S\)到\(T\)的最短路即为答案。

实现细节就看代码吧

\(code:\)

#include<bits/stdc++.h>
#define maxn 1200000
#define inf 2000000000
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag) x=-x;
}
int n,s,t;
struct edge
{
int to,nxt,v;
}e[maxn];
int head[maxn],edge_cnt;
void add(int from,int to,int val)
{
e[++edge_cnt]=(edge){to,head[from],val};
head[from]=edge_cnt;
}
int num(int x,int y)
{
return y+(x-1)*n;
}
struct node
{
int val,num;
friend bool operator <(const node &x,const node &y)
{
return x.val>y.val;
}
};
priority_queue<node> q;
int dis[maxn];
bool vis[maxn];
void dijkstra()
{
for(int i=s;i<=t;++i) dis[i]=inf;
dis[s]=0;
q.push((node){0,s});
while(!q.empty())
{
node tmp=q.top();
q.pop();
int x=tmp.num;
if(vis[x]) continue;
vis[x]=true;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to,v=e[i].v;
if(dis[y]>dis[x]+v)
{
dis[y]=dis[x]+v;
q.push((node){dis[y],y});
}
}
}
}
int main()
{
read(n),n++;
t=n*n+1;
for(int i=1;i<=n;++i)
{
for(int j=1;j<n;++j)
{
int val;
read(val);
if(i==1) add(s,num(i,j),val);
else if(i==n) add(num(i-1,j),t,val);
else add(num(i-1,j),num(i,j),val);
}
}
for(int i=1;i<n;++i)
{
for(int j=1;j<=n;++j)
{
int val;
read(val);
if(j==1) add(num(i,j),t,val);
else if(j==n) add(s,num(i,j-1),val);
else add(num(i,j),num(i,j-1),val);
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<n;++j)
{
int val;
read(val);
if(i==1) add(num(i,j),s,val);
else if(i==n) add(t,num(i-1,j),val);
else add(num(i,j),num(i-1,j),val);
}
}
for(int i=1;i<n;++i)
{
for(int j=1;j<=n;++j)
{
int val;
read(val);
if(j==1) add(t,num(i,j),val);
else if(j==n) add(num(i,j-1),s,val);
else add(num(i,j-1),num(i,j),val);
}
}
dijkstra();
printf("%d",dis[t]);
return 0;
}

最新文章

  1. SQL SERVER 分页查询
  2. 使用XtraReport的CalculatedFiled(计算字段)实现RDLC报表中表达式
  3. 2. XAML
  4. Objective-C 编码规范
  5. redhat6.4升级openssh至6.7
  6. php 图片压缩
  7. JSON.stringify 语法实例讲解 字符串
  8. python课时二
  9. 解决mybatis空字段null字段不返回
  10. SM4加密算法实现Java和C#相互加密解密
  11. &lt;&lt;让你自己的APP成为系统应用&gt;&gt;所遇到的问题及解决方法
  12. python3百度设置高级搜索例子
  13. Linux LVM 逻辑分区
  14. Coursera, Machine Learning, Neural Networks: Representation - week4/5
  15. SQL UPDATE嵌套使用
  16. Vim 8.0
  17. 使用 FreeCAD 打开 KiCad 用于制作外壳
  18. 作为一个有B格的前端工程师需要掌握的一些知识
  19. Inner Classes with TypeScript
  20. C#大数据循环

热门文章

  1. 图解 Git 基本命令 merge 和 rebase
  2. 利用c++中的设计灵感,既要学BIM分类信息表,借助GIS完成环境搭建改善
  3. msf stagers开发不完全指北(二)
  4. 手摸手带你理解Vue的Watch原理
  5. 119.杨辉三角II
  6. 浅谈hash
  7. 解决Centos7下中文显示乱码
  8. 4 个好用的 Linux 监控工具
  9. spark | 手把手教你用spark进行数据预处理
  10. 记一次解密wireshark抓取的冰蝎通信流量