您的位置:首页 > 理论基础 > 计算机网络

网络流二十四题之十六 —— 数字梯形问题(DIGIT)

2016-05-19 16:17 405 查看

数字梯形问题

Description

给定一个由 n 行数字组成的数字梯形如下图所示。



梯形的第一行有 m 个数字。

从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶

至底的路径。

规则1:从梯形的顶至底的 m 条路径互不相交。

规则2:从梯形的顶至底的 m 条路径仅在数字结点处相交。

规则3:从梯形的顶至底的 m 条路径允许在数字结点相交或边相交。

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

Input

第 1 行中有 2 个正整数 m 和 n(m,n<=20),分别表示数字梯形的第一行有 m 个数字,共有 n 行。

接下来的 n 行是数字梯形中各行的数字。

第 1 行有 m 个数字,第 2 行有 m+1 个数字,…。

Output

将按照规则1,规则2,和规则3计算出的最大数字总和输出。

每行一个最大总和。

Sample Input

2 5

2 3

3 4 5

9 10 9 1

1 1 10 1 1

1 1 10 12 1 1

Sample Output

66

75

77

Solution

很简单的费用流题目——只要拆点就可以了。

Code

[cpp] #include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>

#define PLA(x,y) PLA[(x)][(y)]
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
#define ANOTHER 2000
#define INF 0x3f3f3f3f
#define ss 0
#define tt 5000

using namespace std;

int n,m,tmp,ans,cnt;

int maps[100][100];
int f[100][100];
int head[10010],nxt[1000100],wei[1000100],flow[1000100],data[1000100];
int PLA[1000][1000];
int dis[10010];
int pre[10010];
bool in_stack[10010];
queue<int>q;

void add(int x,int y,int a,int b){
nxt[cnt]=head[x];data[cnt]=y;wei[cnt]=b;flow[cnt]=a;head[x]=cnt++;
nxt[cnt]=head[y];data[cnt]=x;wei[cnt]=-b;flow[cnt]=0;head[y]=cnt++;
}

bool BFS(){
memset(dis,0x3f,sizeof dis);dis[ss]=0;in_stack[ss]=true;q.push(ss);pre[ss]=pre[tt]=-1;
while(!q.empty()){
int now=q.front();
q.pop();
in_stack[now]=false;
for(int i=head[now];i!=-1;i=nxt[i]){
if(flow[i]!=0&&dis[data[i]]>dis[now]+wei[i]){
dis[data[i]]=dis[now]+wei[i];
pre[data[i]]=i^1;
if(!in_stack[data[i]]){
in_stack[data[i]]=true;
q.push(data[i]);
}
}
}
}
return pre[tt]!=-1;
}

void dfs(){
int Low=INF;
for(int i=pre[tt];i!=-1;i=pre[data[i]])Low=Min(Low,flow[i^1]);
for(int i=pre[tt];i!=-1;i=pre[data[i]])flow[i^1]-=Low,flow[i]+=Low;
ans+=Low*dis[tt];
}

int main(){

freopen(”digit.in”,“r”,stdin);
freopen(”digit.out”,“w”,stdout);

memset(head,-1,sizeof head);

scanf(”%d%d”,&m,&n);tmp=m;

int tot=0;
for(int i=1;i<=n;i++,tmp++)
for(int j=1;j<=tmp;j++)
PLA[i][j]=++tot;
tmp=m;
for(int i=1;i<=n;i++,tmp++)
for(int j=1;j<=tmp;j++){
scanf(”%d”,&maps[i][j]);
if(i!=n){
add(PLA(i,j),PLA(i+1,j)+ANOTHER,1,0);
add(PLA(i,j),PLA(i+1,j+1)+ANOTHER,1,0);
}
}

for(int i=1;i<=n+m-1;i++)add(PLA(n,i),tt,1,0);
for(int i=1;i<=m;i++)add(ss,PLA(1,i)+ANOTHER,1,0);

tmp=m;
for(int i=1;i<=n;i++,tmp++)
for(int j=1;j<=tmp;j++)
add(PLA(i,j)+ANOTHER,PLA(i,j),1,-maps[i][j]);

while(BFS())dfs();
printf(”%d\n”,-ans);

memset(head,-1,sizeof head);
cnt=0;

for(int i=1;i<=m;i++)add(ss,PLA(1,i),1,0);
for(int i=1;i<=n+m-1;i++)add(PLA(n,i),tt,INF,-maps
[i]);

tmp=m;
for(int i=1;i<=n;i++,tmp++)
for(int j=1;j<=tmp;j++){
if(i!=n){
add(PLA(i,j),PLA(i+1,j),1,-maps[i][j]);
add(PLA(i,j),PLA(i+1,j+1),1,-maps[i][j]);
}
}
ans=0;
while(BFS())
dfs();
printf(”%d\n”,-ans);

ans=0;
tmp=n+m-2;

for(int i=1;i<=tmp+1;i++)f
[i]=maps
[i];
for(int i=n-1;i>=1;i–,tmp–)
for(int j=1;j<=tmp;j++)
f[i][j]=Max(f[i+1][j],f[i+1][j+1])+maps[i][j];
for(int i=1;i<=m;i++)ans+=f[1][i];
printf(”%d\n”,ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: