网络流二十四题之十六 —— 数字梯形问题(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 52 3
3 4 5
9 10 9 1
1 1 10 1 1
1 1 10 12 1 1
Sample Output
6675
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;
}
相关文章推荐
- Python网络编程10----django分页
- Retrofit文件上传与下载(xjh 这应该是retrofit1的代码 亲测不行)___http://www.ithao123.cn/content-7813575.html
- ExpandableListView使用,点击条目请求网络数据,箭头在右边
- 图解Wireshark协议分析实例
- IIS http 错误 401.3 - unauthorized
- HttpOnly 与cookie安全
- okHttp 使用HTTPS证书
- HttpClient发送文件与报文
- HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求。
- 网络协议概述:物理层、连接层、网络层、传输层、应用层详解
- 最小路径覆盖问题[网络流24题之3]
- UNIX网络编程:消息队列
- 卷积神经网络(CNN)在句子建模上的应用
- 基于振动图像纹理特征识别 的滚动轴承故障程度诊断方法研究
- TCP/IP协议与UDP/IP协议的区别
- Android----ListView的使用--->加载网络图片
- 微博营销实战4——网络舆论的监控与应对
- VirtualBox centos 6.5 minimal 开启网络
- 设置fedora23的网络配置
- 封装HttpURLConnection