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

«编程任务:
对于给定的数字梯形,分别按照规则1,规则2,和规则3 计算出从梯形的顶至底的m
条路径,使这m条路径经过的数字总和最大。
«数据输入:
由文件digit.in提供输入数据。文件的第1 行中有2个正整数m和n(m,n<=20),分别
表示数字梯形的第一行有m个数字,共有n 行。接下来的n 行是数字梯形中各行的数字。
第1 行有m个数字,第2 行有m+1 个数字,…。
«结果输出:
程序运行结束时,将按照规则1,规则2,和规则3 计算出的最大数字总和输出到文件
digit.out中。每行一个最大总和。
输入文件示例 输出文件示例
digit.in
2 5
2 3
3 4 5
9 10 9 1
1 1 10 1 1

1 1 10 12 1 1

digit.out

66
75
77

  1. /*
  2. 第一个建图就是拆点(保证每个点只走一次),第二个建图是把两个点之间的边设为1,第三个inf随意搞。
  3. */
  4. #include<cstdio>
  5. #include<iostream>
  6. #include<queue>
  7. #include<cstring>
  8. #define N 4010
  9. #define inf 1000000000
  10. using namespace std;
  11. int a[N][N],head[N],dis[N],inq[N],fa[N],n,m,num,cnt,S,T;
  12. struct node{int u,v,pre,f,w;}e[N];
  13. void add(int u,int v,int f,int w){
  14. e[++cnt].u=u;e[cnt].v=v;e[cnt].f=f;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt;
  15. e[++cnt].u=v;e[cnt].v=u;e[cnt].f=;e[cnt].w=-w;e[cnt].pre=head[v];head[v]=cnt;
  16. }
  17. bool spfa(){
  18. for(int i=;i<=T;i++) dis[i]=inf;
  19. queue<int> q;q.push(S);inq[S]=;dis[S]=;
  20. while(!q.empty()){
  21. int u=q.front();q.pop();inq[u]=;
  22. for(int i=head[u];i;i=e[i].pre)
  23. if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w){
  24. dis[e[i].v]=dis[u]+e[i].w;
  25. fa[e[i].v]=i;
  26. if(!inq[e[i].v]){
  27. inq[e[i].v]=;
  28. q.push(e[i].v);
  29. }
  30. }
  31. }
  32. return dis[T]!=inf;
  33. }
  34. void mincost(){
  35. int cost=;
  36. while(spfa()){
  37. int tmp=fa[T],x=inf;
  38. while(tmp){
  39.  
  40. int u=e[tmp].u;
  41.  
  42. x=min(x,e[tmp].f);
  43. tmp=fa[e[tmp].u];
  44. }
  45. tmp=fa[T];
  46. while(tmp){
  47. e[tmp].f-=x;
  48. e[tmp^].f+=x;
  49. tmp=fa[e[tmp].u];
  50. }
  51. cost+=x*dis[T];
  52. }
  53. printf("%d\n",-cost);
  54. }
  55. int hao(int i,int j){
  56. return (m*+i-)*(i-)/+j;
  57. }
  58. void build1(){
  59. cnt=;memset(head,,sizeof(head));
  60. for(int i=;i<=m;i++)
  61. add(S,i,,-a[][i]);
  62. for(int i=;i<n;i++)
  63. for(int j=;j<=m+i-;j++)
  64. add(hao(i,j)+num,hao(i+,j),,-a[i+][j]),add(hao(i,j)+num,hao(i+,j+),,-a[i+][j+]);
  65. for(int i=;i<=m+n-;i++)
  66. add(hao(n,i)+num,T,,);
  67. for(int i=;i<=n;i++)
  68. for(int j=;j<=m+i-;j++)
  69. add(hao(i,j),hao(i,j)+num,,);
  70.  
  71. }
  72. void build2(){
  73. cnt=;memset(head,,sizeof(head));
  74. for(int i=;i<=m;i++)
  75. add(S,i,,-a[][i]);
  76. for(int i=;i<=n;i++)
  77. for(int j=;j<=m+i-;j++)
  78. add(hao(i,j),hao(i+,j),,-a[i+][j]),add(hao(i,j),hao(i+,j+),,-a[i+][j+]);
  79. for(int i=;i<=m+n-;i++)
  80. add(hao(n,i),T,inf,);
  81. }
  82. void build3(){
  83. cnt=;memset(head,,sizeof(head));
  84. for(int i=;i<=m;i++)
  85. add(S,i,,-a[][i]);
  86. for(int i=;i<=n;i++)
  87. for(int j=;j<=m+i-;j++)
  88. add(hao(i,j),hao(i+,j),inf,-a[i+][j]),add(hao(i,j),hao(i+,j+),inf,-a[i+][j+]);
  89. for(int i=;i<=m+n-;i++)
  90. add(hao(n,i),T,inf,);
  91. }
  92. int main(){
  93. scanf("%d%d",&m,&n);num=(m*+n-)*n/;
  94. S=;T=num*+;
  95. for(int i=;i<=n;i++)
  96. for(int j=;j<=m+i-;j++)
  97. scanf("%d",&a[i][j]);
  98. build1();mincost();
  99. build2();mincost();
  100. build3();mincost();
  101. return ;
  102. }

数字梯形(cogs 738)的更多相关文章

  1. COGS738 [网络流24题] 数字梯形(最小费用最大流)

    题目这么说: 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径.规则1:从梯形的 ...

  2. 【wikioi】1913 数字梯形问题(费用流)

    http://wikioi.com/problem/1913/ 如果本题没有询问2和3,那么本题和蚯蚓那题一模一样.http://www.cnblogs.com/iwtwiioi/p/3935039. ...

  3. 【网络流24题】No.16 数字梯形问题 (不相交路径 最大费用流)

    [题意] 给定一个由 n 行数字组成的数字梯形如下图所示. 梯形的第一行有 m 个数字.从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动, 形成一条从梯形的顶至底的路径.规则 1: ...

  4. codevs 1913 数字梯形问题 费用流

    题目链接 给你一个数字梯形, 最上面一层m个数字, 然后m+1,......m+n-1个. n是层数. 在每个位置, 可以向左下或右下走.然后让你从最顶端的m个数字开始, 走出m条路径, 使得路过的数 ...

  5. P4013 数字梯形问题 网络流

    题目描述 给定一个由 nn 行数字组成的数字梯形如下图所示. 梯形的第一行有 mm 个数字.从梯形的顶部的 mm 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径. 分别 ...

  6. 【刷题】LOJ 6010 「网络流 24 题」数字梯形

    题目描述 给定一个由 \(n\) 行数字组成的数字梯形如下图所示.梯形的第一行有 \(m\) 个数字.从梯形的顶部的 \(m\) 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至 ...

  7. Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)

    Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...

  8. P4013 数字梯形问题 网络流二十四题

    P4013 数字梯形问题 题目描述 给定一个由 nn 行数字组成的数字梯形如下图所示. 梯形的第一行有 m 个数字.从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形 ...

  9. 【费用流】【网络流24题】【P4013】 数字梯形问题

    Description 给定一个由 \(n\) 行数字组成的数字梯形如下图所示. 梯形的第一行有 \(m\) 个数字.从梯形的顶部的 \(m\) 个数字开始,在每个数字处可以沿左下或右下方向移动,形成 ...

随机推荐

  1. 新建maven的pom.xml第一行出错的解决思路

    前言:博主在想要用maven创建项目的时候,忘记之前已经安装过maven了,所以再安装了另一个版本的maven,导致在pom.xml的第一行总是显示某一个jar的zip文件读取不出来. 在网上找了很多 ...

  2. shiro 配置拦截规则之后css和js等失效

    使用shiro作为平台的权限管理工具,shiro的配置文件如下: package com.ros.config; import java.util.LinkedHashMap;import java. ...

  3. 历史管理 onhashchange

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. python基础一 day14 复习

    迭代器和生成器迭代器:双下方法 : 很少直接调用的方法.一般情况下,是通过其他语法触发的可迭代的 —— 可迭代协议 含有__iter__的方法('__iter__' in dir(数据))可迭代的一定 ...

  5. node mocha mochawesome报安装不成功

    1.进行cnpm安装: npm install cnpm -g --registry=https://registry.npm.taobao.org 2.查看cnpm版本 cnpm -v 3.安装mo ...

  6. java 去掉html/style/css等标签

    //定义script的正则表达式 private static String regEx_script="<script[^>]*?>[\\s\\S]*?<\\/sc ...

  7. 安装vc++6.0的步骤

    我们学习计算机,就必须要先将编程的c语言学好,打好基础,学习c语言最好的方法就是多上机联系,对于联系我们需要在自己的电脑上安装vc++6.0来进行平日里的联系.1.打开电脑进行联网,打开浏览器搜索vc ...

  8. CF-1099 D. Sum in the tree

    CF-1099 D. Sum in the tree 题意:结点序号为 1~n 的一个有根树,根序号为1,每个点有一个权值a[i], 然后定义一s[i]表示从根节点到 结点序号为i的结点的路途上所经过 ...

  9. HDU-2544-最短路(Bellman-Ford)

    Bellman-Ford算法是一个时间复杂度很高,但是它可以用来判断负环 负环就是上面的图,那个环的整体值小于零了,所以就是负环. 我们用Bellman-Ford算法进行更新,打一个表出来: k a ...

  10. Linux菜鸟起飞之路【四】绝对路径、相对路径及常用目录

    一.绝对路径与相对路径 Linux操作系统中存在着两种路径:绝对路径和相对路径.我们在访问文件或文件夹的时候,其实都是通过路径来操作的.两种路径在实际操作中能起到同等的作用. 在开始具体介绍之前,我们 ...