738. [网络流24题] 数字梯形
★★★☆ 输入文件:digit.in
输出文件:digit.out
时间限制:1 s 内存限制:128 MB
«问题描述:
给定一个由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
哈哈哈哈哈!
今天皮了一下,某dalao学长。
2333.
很开心。
今儿my goddess蒽的混进学校来看我啦!
mmp居然穿的那么好看,
mmp搞得像她是我闺女似的
23333而且还蹭了学妹的一大杯饮料,
乐事!零食!
天呐,你们都太壕了。
切入正题,
这两天硬灌network flow。。。
就是不自量力怎样!
就要very unique!
宁死也要跟61级混!
so,
思路:
work1建图拆点,保证每个点只走一次;
work2建图把两个点之间的边设为1,
work3随便写。
ac代码:(wow,有生之来第一次写(抄)这么长的代码耶,amazing)。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 #define N 4010 8 #define inf 1000000000 9 using namespace std; 10 11 int a[N][N],head[N],dis[N],inq[N],fa[N],n,m,num,cnt,S,T; 12 13 struct node 14 { 15 int u,v,pre,f,w; 16 } e[N]; 17 18 void add(int u,int v,int f,int w) 19 { 20 e[++cnt].u =u; 21 e[cnt].v =v; 22 e[cnt].f =f; 23 e[cnt].w =w; 24 e[cnt].pre =head[u]; 25 head[u]=cnt; 26 e[++cnt].u =v; 27 e[cnt].v =u; 28 e[cnt].f =0; 29 e[cnt].w =-w; 30 e[cnt].pre =head[v]; 31 head[v]=cnt; 32 } 33 34 bool bfs() 35 { 36 for(int i=0; i<=T; ++i) 37 dis[i]=inf; 38 queue<int>q; 39 q.push(S); 40 inq[S]=1; 41 dis[S]=0; 42 while(!q.empty()) 43 { 44 int u=q.front(); 45 q.pop(); 46 inq[u]=0; 47 for(int i=head[u]; i; i=e[i].pre ) 48 if(e[i].f &&dis[e[i].v ]>dis[u]+e[i].w ) 49 { 50 dis[e[i].v ]=dis[u]+e[i].w ; 51 fa[e[i].v ]=i; 52 if(!inq[e[i].v ]) 53 { 54 inq[e[i].v ]=1; 55 q.push(e[i].v ); 56 } 57 } 58 } 59 return dis[T]!=inf; 60 } 61 62 void mincost() 63 { 64 int cost=0; 65 while(bfs()) 66 { 67 int tmp=fa[T],x=inf; 68 while(tmp) 69 { 70 int u=e[tmp].u ; 71 x=min(x,e[tmp].f ); 72 tmp=fa[e[tmp].u ]; 73 } 74 tmp=fa[T]; 75 while(tmp) 76 { 77 e[tmp].f -=x; 78 e[tmp^1].f +=x; 79 tmp=fa[e[tmp].u ]; 80 } 81 cost+=x*dis[T]; 82 } 83 printf("%d ",-cost); 84 } 85 86 int good(int i,int j) 87 { 88 return (m*2+i-2)*(i-1)/2+j; 89 } 90 91 void work1() 92 { 93 cnt=1; 94 memset(head,0,sizeof(head)); 95 for(int i=1; i<=m; ++i) 96 add(S,i,1,-a[1][i]); 97 for(int i=1; i<n; ++i) 98 for(int j=1; j<=m+i-1; ++j) 99 { 100 add(good(i,j)+num,good(i+1,j),1,-a[i+1][j]); 101 add(good(i,j)+num,good(i+1,j+1),1,-a[i+1][j+1]); 102 } 103 for(int i=1; i<=m+n-1; ++i) 104 add(good(n,i)+num,T,1,0); 105 for(int i=1; i<=n; ++i) 106 for(int j=1; j<=m+i-1; ++j) 107 add(good(i,j),good(i,j)+num,1,0); 108 } 109 110 void work2() 111 { 112 cnt=1; 113 memset(head,0,sizeof(head)); 114 for(int i=1;i<=m;++i) 115 add(S,i,1,-a[1][i]); 116 for(int i=1; i<=n; ++i) 117 for(int j=1; j<=m+i-1; ++j) 118 { 119 add(good(i,j),good(i+1,j),1,-a[i+1][j]); 120 add(good(i,j),good(i+1,j+1),1,-a[i+1][j+1]); 121 } 122 for(int i=1; i<=m+n-1; ++i) 123 add(good(n,i),T,inf,0); 124 } 125 126 void work3() 127 { 128 cnt=1; 129 memset(head,0,sizeof(head)); 130 for(int i=1; i<=m; ++i) 131 add(S,i,1,-a[1][i]); 132 for(int i=1; i<=n; ++i) 133 for(int j=1; j<=m+i-1; ++j) 134 { 135 add(good(i,j),good(i+1,j),inf,-a[i+1][j]); 136 add(good(i,j),good(i+1,j+1),inf,-a[i+1][j+1]); 137 } 138 for(int i=1; i<=m+n-1; ++i) 139 add(good(n,i),T,inf,0); 140 } 141 142 int main() 143 { 144 freopen("digit.in","r",stdin); 145 freopen("digit.out","w",stdout); 146 scanf("%d%d",&m,&n); 147 num=(m*2+n-1)*n/2; 148 S=0; 149 T=num*2+1; 150 for(int i=1; i<=n; ++i) 151 for(int j=1; j<=m+i-1; ++j) 152 scanf("%d",&a[i][j]); 153 work1(); 154 mincost(); 155 work2(); 156 mincost(); 157 work3(); 158 mincost(); 159 return 0; 160 }
如果你不开心,那我就把右边
这个帅傻子分享给你吧,
你看,他这么好看,跟个zz一样看着你,你还伤心吗?
真的!这照片盯上他五秒钟就想笑了。
一切都会过去的。
时间时间会给你答案2333