• 网络流24题-数字梯形问题


    数字梯形问题

     

    题目描述

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

    梯形的第一行有 m 个数字。从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。

    分别遵守以下规则:

    1. 从梯形的顶至底的 m 条路径互不相交;

    2. 从梯形的顶至底的 m 条路径仅在数字结点处相交;

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

    输入输出格式

    输入格式:

    第 1 行中有 2 个正整数 m 和 n ,分别表示数字梯形的第一行有 m 个数字,共有 n 行。接下来的 n 行是数字梯形中各行的数字。

    第 1 行有 m 个数字,第 2 行有 m+1 个数字,以此类推。

    输出格式:

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

    输入输出样例

    输入样例: 
    2 5
    2 3
    3 4 5
    9 10 9 1
    1 1 10 1 1
    1 1 10 12 1 1
    输出样例: 
    66
    75
    77

    说明

    1m,n20


    费用流。
    找好约束条件是在点上还是边上就好了。
    #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
    ",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
    ",-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
    ",-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
    ",-cost);
        
        return 0;
    }
    View Code
  • 相关阅读:
    C++中的指针和数组
    windows系统下JDK1.6环境变量配置
    Java Reflection (JAVA反射)
    转载:cin深入分析(下) – cin的错误处理
    OpenGL总结
    OpenGL纹理
    c/C++内存分配
    转载:cin深入分析(上) – cin输入操作处理
    c++中string的用法
    OpenGL颜色
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9539753.html
Copyright © 2020-2023  润新知