网络流24题 -No.16 数字梯形问题

问题描述
    给定一个由 n 行数字组成的数字梯形如下图所示。梯形的第一行有 m 个数字。从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。
    规则 1:从梯形的顶至底的 m条路径互不相交。
    规则 2:从梯形的顶至底的 m条路径仅在数字结点处相交。
    规则 3:从梯形的顶至底的 m条路径允许在数字结点相交或边相交。
    2   3

3   4   5

9   10   9   1

1   1   10   1   1

1   1   10   12   1   1

编程任务
    对于给定的数字梯形,分别按照规则 1,规则 2,和规则 3 计算出从梯形的顶至底的 m条路径,使这 m条路径经过的数字总和最大。

数据输入

输入文件的第 1 行中有 2个正整数 m和 n(m,n<=20),分别表示数字梯形的第一行有 m 个数字,共有 n 行。接下来的 n 行是数字梯形中各行的数字。
第 1 行有 m个数字,第 2 行有 m+1 个数字,…。

结果输出
程序运行结束时,输出按照规则 1,规则 2,和规则 3 计算出的最大数字总和。

输入文件示例

2 5

2 3

3 4 5

9 10 9 1

1 1 10 1 1

1 1 10 12 1 1

输出文件示例

66

75

77

【问题分析】

求图的最大权不相交路径及其变种,用费用最大流解决。

【建模方法】

规则(1)

把梯形中每个位置抽象为两个点<i.a>,<i.b>,建立附加源S汇T。

1、对于每个点i从<i.a>到<i.b>连接一条容量为1,费用为点i权值的有向边。
2、从S向梯形顶层每个<i.a>连一条容量为1,费用为0的有向边。
3、从梯形底层每个<i.b>向T连一条容量为1,费用为0的有向边。
4、对于每个点i和下面的两个点j,分别连一条从<i.b>到<j.a>容量为1,费用为0的有向边。

求最大费用最大流,费用流值就是结果。

规则(2)

把梯形中每个位置看做一个点i,建立附加源S汇T。

1、从S向梯形顶层每个i连一条容量为1,费用为0的有向边。
2、从梯形底层每个i向T连一条容量为无穷大,费用为点i权值的有向边。
3、对于每个点i和下面的两个点j,分别连一条从i到j容量为1,费用为点i权值的有向边。

求最大费用最大流,费用流值就是结果。

规则(3)

把梯形中每个位置看做一个点i,建立附加源S汇T。

1、从S向梯形顶层每个i连一条容量为1,费用为0的有向边。
2、从梯形底层每个i向T连一条容量为无穷大,费用为点i权值的有向边。
3、对于每个点i和下面的两个点j,分别连一条从i到j容量为无穷大,费用为点i权值的有向边。

求最大费用最大流,费用流值就是结果。

【建模分析】

对于规则1,要求路径完全不相交,也就是每个点最多只能被访问了一次,所以要把点拆分,之间连接容量为1的边。因为任意一条ST之间的路径都是一个解,在拆分的点内部的边费用设为点的权值,求最大费用最大流就是费用最大的m条路经。

对于规则2,要求路径可以相交,但不能有重叠,此时可以不必拆点了。为了保证路径没有重叠,需要在相邻的两个点上限制流量为1,由于顶层的每个点只能用1次,S向顶层点流量限制也为1。费用只需设在相邻点的边上,求最大费用最大流即可。

对于规则3,要求路径除了顶层每个点以外可以任意相交重叠。在规则2的基础上,取消除S到顶层顶点之间的边以外所有边的流量限制即可。

代码:

  1 const
  2   maxn=1 << 30;
  3
  4 var
  5   ot,cost,ne,cap,h:array[0..30000]of longint;
  6   g,pre,dis:array[0..1010]of longint;
  7   a,find:array[1..40,1..40]of longint;
  8   inq:array[0..1010]of boolean;
  9   e,s,t,c,i,n,m,ans,j:longint;
 10
 11 procedure addedge(x,y,z,w:longint);
 12 begin
 13   ot[e]:=y; cap[e]:=z; ne[e]:=g[x]; cost[e]:=-w; g[x]:=e; inc(e);
 14   ot[e]:=x; cap[e]:=0; ne[e]:=g[y]; cost[e]:=w; g[y]:=e; inc(e);
 15 end;
 16
 17 function min(a,b:longint):longint;
 18 begin
 19   if a<b then exit(a) else exit(b);
 20 end;
 21
 22 function spfa:boolean;
 23 var
 24   x,y,l,r,p:longint;
 25 begin
 26   for i:=s to t do
 27     begin dis[i]:=maxn; inq[i]:=false; end;
 28   l:=0; r:=1; dis[s]:=0; inq[s]:=true; h[1]:=s; pre[s]:=-1;
 29   while l<r do
 30     begin
 31       inc(l);
 32       x:=h[l];
 33       p:=g[x];
 34       while p>-1 do
 35         begin
 36           y:=ot[p];
 37           if (cap[p]>0)and(dis[y]>dis[x]+cost[p])
 38             then begin
 39                    dis[y]:=dis[x]+cost[p]; pre[y]:=p;
 40                    if inq[y]=false
 41                      then begin inq[y]:=true; inc(r); h[r]:=y; end;
 42                  end;
 43           p:=ne[p];
 44         end;
 45       inq[x]:=false;
 46     end;
 47   exit(dis[t]<>maxn);
 48 end;
 49
 50 function find_path:longint;
 51 var
 52   x,p,tmp,path:longint;
 53 begin
 54   x:=t; path:=maxn; tmp:=0;
 55   while x>s do
 56     begin
 57       p:=pre[x];
 58       path:=min(path,cap[p]);
 59       x:=ot[p xor 1];
 60     end;
 61   x:=t;
 62   while x>s do
 63     begin
 64       p:=pre[x];
 65       inc(tmp,path*cost[p]);
 66       inc(cap[p xor 1],path);
 67       dec(cap[p],path);
 68       x:=ot[p xor 1];
 69     end;
 70   exit(tmp);
 71 end;
 72
 73 procedure work1;
 74 begin
 75   s:=0; t:=find[n,m+n-1]*2+1; ans:=0; e:=0;
 76   fillchar(g,sizeof(g),255);
 77   for i:=1 to n do
 78     for j:=1 to m+i-1 do addedge(find[i,j]*2-1,find[i,j]*2,1,a[i,j]);
 79   for i:=1 to m do addedge(s,2*i-1,1,0);
 80   for i:=find[n,1] to find[n,m+n-1] do addedge(2*i,t,1,0);
 81   for i:=1 to n-1 do
 82     for j:=1 to m+i-1 do
 83       begin
 84         addedge(find[i,j]*2,find[i+1,j]*2-1,1,0);
 85         addedge(find[i,j]*2,find[i+1,j+1]*2-1,1,0);
 86       end;
 87   while spfa do
 88     inc(ans,find_path);
 89   writeln(-ans);
 90 end;
 91
 92 procedure work2(x:longint);
 93 begin
 94   s:=0; t:=find[n,m+n-1]+1; ans:=0; e:=0;
 95   fillchar(g,sizeof(g),255);
 96   for i:=1 to m do addedge(s,i,1,0);
 97   for i:=1 to m+n-1 do addedge(find[n,i],t,maxn,a[n,i]);
 98   for i:=1 to n-1 do
 99     for j:=1 to m+i-1 do
100       if x=1
101         then begin
102                addedge(find[i,j],find[i+1,j],1,a[i,j]);
103                addedge(find[i,j],find[i+1,j+1],1,a[i,j]);
104              end
105         else begin
106                addedge(find[i,j],find[i+1,j],maxn,a[i,j]);
107                addedge(find[i,j],find[i+1,j+1],maxn,a[i,j]);
108              end;
109   while spfa do
110     inc(ans,find_path);
111   writeln(-ans);
112 end;
113
114 begin
115   readln(m,n);
116   for i:=1 to n do
117     for j:=1 to m+i-1 do
118       begin
119         read(a[i,j]);
120         find[i,j]:=(2*m+i-2)*(i-1) div 2+j;
121       end;
122   work1;
123   work2(1);
124   work2(2);
125 end.
时间: 2024-10-10 21:57:37

网络流24题 -No.16 数字梯形问题的相关文章

LOJ #6010. 「网络流 24 题」数字梯形

#6010. 「网络流 24 题」数字梯形 题目描述 给定一个由 n nn 行数字组成的数字梯形如下图所示.梯形的第一行有 m mm 个数字.从梯形的顶部的 m mm 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径. 分别遵守以下规则: 从梯形的顶至底的 m mm 条路径互不相交: 从梯形的顶至底的 m mm 条路径仅在数字结点处相交: 从梯形的顶至底的 m mm 条路径允许在数字结点相交或边相交. 输入格式 第 1 11 行中有 2 22 个正整数 m mm 和

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

[网络流24题]魔术球问题

问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只能在某根柱子的最上面放球. (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在n根柱子上最多能放多少个球.例如,在4 根柱子上最多可放11个球. ´编程任务: 对于给定的n,计算在 n根柱子上最多能放多少个球. ´数据输入: 文件第1 行有 1个正整数n,表示柱子数. ´结果输出: 文件的第一行是球数. 数据规模 n<=60  保证答案小于16

[网络流24题] 搭配飞行员

14. [网络流24题] 搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 如图,假设有10个驾驶员,如图中的V1,V2,…,V10就代表达10个驾驶员,其中V1,V2,

网络流24题刷题记录

题目一:飞行员配对方案问题 一群飞行员和另一群飞行员之间有的可以配对,有的不能配对,求最多可以配多少对? 典型二分图最大匹配问题.可以用匈牙利算法 或者 加上源点汇点之后跑最大流.[感觉第二个打错的概率还低一些]. [还是介绍一下匈牙利算法吧][看白书大法好!] 从左边(s集)一个未盖点出发(还有没有和任何人匹配的点)出发,顺次经过未选边->选边->未选边.....[这样的路叫做交替路] 如果路径当中经过一个未盖点[这样的交替路叫增广路]...那么将所有的选边变成不选,不选的边选上,就可以多一

14. [网络流24题] 搭配飞行员

14. [网络流24题] 搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述] 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 如图,假设有10个驾驶员,如图中的V1,V2,…,V10就代表达10个驾驶员,其中V1,V2

[COGS 0014][网络流24题] 搭配飞行员

先贴题面 14. [网络流24题] 搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out简单对比时间限制:1 s   内存限制:128 MB [问题描述] 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 如图,假设有10个驾驶员,如图中的V1,V2,…,V10就代表达10个驾驶员,其中V1,V

cogs_14_搭配飞行员_(二分图匹配+最大流,网络流24题#01)

描述 http://cojs.tk/cogs/problem/problem.php?pid=14 有一些正飞行员和副飞行员,给出每个正飞行员可以和哪些副飞行员一起飞.一架飞机上必须一正一副,求最多多少飞机可以飞. 分析 裸的二分图匹配... 请叫我水题小王子... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100+5,INF=0x7fffffff; 5 int n,m,cnt=1; 6 int l

【网络流24题】No.1 搭配飞行员(飞行员配对方案问题)

[问题描述] 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 如图,假设有10个驾驶员,如图中的V1,V2,-,V10就代表达10个驾驶员,其中V1,V2,V3,V4,V5是正驾驶员,V6,V7,V8,V9,V10是副驾驶员.如果一个正驾驶员和一个副驾驶员可以同机飞行,就在代表他们两个之间连一条线,两个人不能同机飞行,就不连