题目描述
给定一个由 n 行数字组成的数字梯形如下图所示。
梯形的第一行有 m 个数字。从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。
分别遵守以下规则:
-
从梯形的顶至底的 m 条路径互不相交;
-
从梯形的顶至底的 m 条路径仅在数字结点处相交;
-
从梯形的顶至底的 m 条路径允许在数字结点相交或边相交。
输入输出格式
输入格式:
第 1 行中有 2 个正整数 m 和 n ,分别表示数字梯形的第一行有 m 个数字,共有 n 行。接下来的 n 行是数字梯形中各行的数字。
第 1 行有 m 个数字,第 2 行有 m+1 个数字,以此类推。
输出格式:
将按照规则 1 ,规则 2 ,和规则 3 计算出的最大数字总和并输出,每行一个最大总和。
输入输出样例
说明
1≤m,n≤20
费用流。
找好约束条件是在点上还是边上就好了。
#include<bits/stdc++.h> #define INF LLONG_MAX/2 #define N 1250 using namespace std; typedef struct { int u,v; long long flow,cost; }ss; ss edg[N*N]; vector<int>edges[N]; int now_edges=0; void addedge(int u,int v,long long flow,long long cost) { cost*=-1; edges[u].push_back(now_edges); edg[now_edges++]=(ss){u,v,flow,cost}; edges[v].push_back(now_edges); edg[now_edges++]=(ss){v,u,0,-cost}; } bool spfa(int s,int t,long long &flow,long long &cost) { // printf("%lld %lld\n",flow,cost); long long dis[N]; for(int i=0;i<N;i++)dis[i]=INF; dis[s]=0; long long maxflow[N]; maxflow[s]=INF; int pre[N]={0}; int vis[N]={0}; vis[s]=1; queue<int>q; q.push(s); while(!q.empty()) { int now=q.front(); q.pop(); vis[now]=0; int Size=edges[now].size(); for(int i=0;i<Size;i++) { ss e=edg[edges[now][i]]; if(e.flow>0&&dis[e.v]>dis[now]+e.cost) { dis[e.v]=dis[now]+e.cost; pre[e.v]=edges[now][i]; maxflow[e.v]=min(maxflow[now],e.flow); if(!vis[e.v]) { q.push(e.v); vis[e.v]=1; } } } } if(dis[t]==INF)return false; flow+=maxflow[t]; cost+=maxflow[t]*dis[t]; int now=t; while(now!=s) { edg[pre[now]].flow-=maxflow[t]; edg[pre[now]^1].flow+=maxflow[t]; now=edg[pre[now]].u; } return true; } void f(int s,int t,long long &flow,long long &cost) { while(spfa(s,t,flow,cost)); } void init() { for(int i=0;i<N;i++)edges[i].clear(); now_edges=0; } long long Map[25][25]; int x[25][25],y[25][25]; int main() { int m,n,cut=1,s,t; scanf("%d %d",&m,&n); for(int i=1;i<=n;i++) for(int j=1;j<=m+i-1;j++) { scanf("%lld",&Map[i][j]); x[i][j]=2*cut-1; y[i][j]=2*cut; cut++; } s=2*cut+1; t=2*cut+2; long long flow=0,cost=0; init(); for(int i=1;i<=m;i++)addedge(s,x[1][i],1,0); for(int i=1;i<=m+n-1;i++)addedge(y[n][i],t,1,0); for(int i=1;i<n;i++) for(int j=1;j<=m+i-1;j++) { addedge(y[i][j],x[i+1][j],1,0); addedge(y[i][j],x[i+1][j+1],1,0); } for(int i=1;i<=n;i++) for(int j=1;j<=m+i-1;j++)addedge(x[i][j],y[i][j],1,Map[i][j]); f(s,t,flow,cost); printf("%lld\n",-cost); flow=0; cost=0; init(); for(int i=1;i<=m;i++)addedge(s,x[1][i],1,0); for(int i=1;i<=m+n-1;i++)addedge(y[n][i],t,INF,0); for(int i=1;i<n;i++) for(int j=1;j<=m+i-1;j++) { addedge(y[i][j],x[i+1][j],1,0); addedge(y[i][j],x[i+1][j+1],1,0); } for(int i=1;i<=n;i++) for(int j=1;j<=m+i-1;j++)addedge(x[i][j],y[i][j],INF,Map[i][j]); f(s,t,flow,cost); printf("%lld\n",-cost); flow=0; cost=0; init(); for(int i=1;i<=m;i++)addedge(s,x[1][i],1,0); for(int i=1;i<=m+n-1;i++)addedge(y[n][i],t,INF,0); for(int i=1;i<n;i++) for(int j=1;j<=m+i-1;j++) { addedge(y[i][j],x[i+1][j],INF,0); addedge(y[i][j],x[i+1][j+1],INF,0); } for(int i=1;i<=n;i++) for(int j=1;j<=m+i-1;j++)addedge(x[i][j],y[i][j],INF,Map[i][j]); f(s,t,flow,cost); printf("%lld\n",-cost); return 0; }