问题描述
给定一个由 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.