题目

现在有一大块土地,可以看成N*M的方格。在这块土地上,有些格子内是崎岖的山地,无法建造任何东西;其他格子都是平原。现在打算在这块土地上建设一个游乐园。游乐园由若干条闭合的过山车轨道组成,每个平原格子都要铺一截轨道,为下列 6 种类型中的一种:



(每张图表示一块平原格子,图内网格线为辅助线,无实际意义。)

其中前 2 种为直轨道,后 4 种为弯轨道。显然对游客来说,弯轨道更加刺激。

由于每块格子风景各不相同,经过一番研究,现给了N*M个方格中的每个格子一个评估值,意义为:如果该格子修建弯轨道,会给游客们带来多少的愉悦值。现需要一名设计师,帮他设计一种最优的轨道建设方案,使所有格子给游客们带来的愉悦值之和尽量大。(如果没有合法方案,输出 -1)

N<=150,M<=30,Vi,j<=100

题解:

乍一看没有什么思路.

但仔细观察一下可以通过直觉感觉出来是网络流。

(OI人的直觉)

在棋盘问题上应用网络流算法,经典的就是黑白染色。

所以我们将棋盘黑白染色。

然后我们考虑怎样构造方案:

  • 一定有每个黑色格子与两个白色格子连接且每个白色格子与两个黑色各自连接.

    如果能达到这个,那么一定可行.

    所以可以用最大流来判断是否可行.

其中每个加粗边的流量是2,然后我们判断一下最大流是否为节点数即可.

那么对于转弯时付出的代价要怎么计算?

我们还是在上述的模型中进行改进,我们对边赋以权值。

然后考虑把点拆成和x方向的白点进行连接与和y方向的白点进行连接两种点。

然后再加一个点来控制到达这两个点的总流量为2。

然后就很明朗了,我们只要完成这么一个限制:如果流量分别走了两边,就获得权值。

... ...

但是经过仔细思考后并不能完成这么一个限制...

所以考虑转化一下。我们知道上述条件等价于:如果流量都走了同一边,就无法获得权值.

这个限制是我们可以简单完成的,只要利用凸费用流的性质即可.

所以跑最小费用最大流即可.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
const int maxn = 160;
const int maxm = 36;
const int maxnode = 3*maxn*maxm;
const int maxedge = maxnode*4;
struct Edge{
int to,next,cost,cap;
}G[maxedge<<1];
int head[maxnode],cnt = 1;
inline void add(int u,int v,int c,int d){
G[++cnt].to = v;
G[cnt].next = head[u];
G[cnt].cap = c;
G[cnt].cost = d;
head[u] = cnt;
}
inline void insert(int u,int v,int c,int d){
add(u,v,c,d);add(v,u,0,-d);
}
#define v G[i].to
const int lim = maxnode<<1;
int q[lim+10],dis[maxnode],p[maxnode];
int flow[maxnode];
int l,r,S,T,fl;ll ans;bool inq[maxnode];
int nodecnt;
const int inf = 0x3f3f3f3f;
inline bool spfa(){
rep(i,1,nodecnt){
dis[i] = inf;
inq[i] = false;
}
l = 0;r = -1;q[++r % lim] = S;
inq[S] = true;flow[S] = inf;
dis[S] = 0;
while(l <= r){
int u = q[l++ % lim];
for(rg i = head[u];i;i=G[i].next){
if(dis[v] > dis[u] + G[i].cost && G[i].cap > 0){
dis[v] = dis[u] + G[i].cost;
flow[v] = min(flow[u],G[i].cap);
p[v] = i;
if(!inq[v]){
q[++r % lim] = v;
inq[v] = true;
}
}
}inq[u] = false;
}if(dis[T] == inf) return false;
ans += 1LL*flow[T]*dis[T];
fl += flow[T];
for(rg u = T;u != S;u = G[p[u]^1].to)
G[p[u]].cap -= flow[T],G[p[u]^1].cap += flow[T];
return true;
}
#undef v
int idx[maxn][maxm],idy[maxn][maxm],id[maxn][maxm];
int main(){
int n,m;read(n);read(m);
int x,num = 0;
rep(i,1,n){
rep(j,1,m){
read(x);
if(x == 0){
++ num;
id[i][j] = ++ nodecnt;
idx[i][j] = ++ nodecnt;
idy[i][j] = ++ nodecnt;
}
}
}
ll tot = 0;
S = ++ nodecnt;T = ++ nodecnt;
rep(i,1,n){
rep(j,1,m){
read(x);
if(id[i][j] == 0) continue;
tot += x;
if((i+j)&1^1){
insert(S,id[i][j],2,0);
insert(id[i][j],idx[i][j],1,0);
insert(id[i][j],idx[i][j],1,x);
insert(id[i][j],idy[i][j],1,0);
insert(id[i][j],idy[i][j],1,x);
}else{
insert(id[i][j],T,2,0);
insert(idx[i][j],id[i][j],1,0);
insert(idx[i][j],id[i][j],1,x);
insert(idy[i][j],id[i][j],1,0);
insert(idy[i][j],id[i][j],1,x);
}
if((i+j)&1^1){
int x,y;
x = i-1;y = j;
if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idx[i][j],idx[x][y],1,0);
x = i+1;y = j;
if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idx[i][j],idx[x][y],1,0);
x = i;y = j-1;
if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idy[i][j],idy[x][y],1,0);
x = i;y = j+1;
if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idy[i][j],idy[x][y],1,0);
}
}
}
while(spfa());
if(fl != nodecnt / 3){
puts("-1");
return 0;
}
printf("%lld\n",tot - ans);
return 0;
}

最新文章

  1. JavaScript随笔1
  2. Python学习路程day16
  3. 打印出所有的 &quot;水仙花数 &quot;,所谓 &quot;水仙花数 &quot;是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个 &quot;水仙花数 &quot;,因为153=1的三次方+5的三次方+3的三次方。
  4. SQLChop、SQLWall(Druid)、PHP Syntax Parser Analysis
  5. ServiceStack.Redis之IRedisClient 03_转
  6. 【转载】Git的安装与使用
  7. 由链表初始化看C语言的二级指针
  8. 1002 A + B Problem II [ACM刷题]
  9. iOS开发-大文件下载与断点下载思路
  10. css基础知识之列表
  11. 【转载】以Java的视角来聊聊SQL注入
  12. 环链表相关的题目和算法[LeetCode]
  13. hdu3966 点权模板-树链部分
  14. 005-mac下Java开发工具安装,idea,maven,git,node
  15. MongoDB--预备
  16. android4.0 中关于内外置sd卡的获取及读写权限问题
  17. Exception in thread &quot;main&quot; java.lang.StackOverflowError
  18. 计蒜客 31001 - Magical Girl Haze - [最短路][2018ICPC南京网络预赛L题]
  19. ubuntu修改运行级别方法
  20. HDU 2123 An easy problem

热门文章

  1. 读书笔记-HBase in Action-第三部分应用-(1)OpenTSDB
  2. [JavaScript] Imitate String.Format() in c#
  3. EasyNVR无插件直播服务器播放页面的集成----单独的播放器样式
  4. DDD开源框架
  5. WORD表格数据运算技巧
  6. 华为机试ACM(字符组合问题)
  7. 内存写越界导致破环堆结构引起的崩溃问题定位经验[如报错malloc(): memory corruption或free(): invalid next size]
  8. git入门篇-----本地操作
  9. MVC ViewBag不能使用在工程文件中添加引用
  10. 用linux搭建ranzhi环境