zoukankan      html  css  js  c++  java
  • [题解] PowerOJ 1751 数字梯形问题 (最大费用最大流)

    - 传送门 -

     https://www.oj.swust.edu.cn/problem/show/1751

    # 1751: 数字梯形问题

    Time Limit: 1000 MS Memory Limit: 65536 KB
    Total Submit: 63 Accepted: 40 Page View: 410

    Description

    给定一个由n 行数字组成的数字梯形如下图所示。梯形的第一行有m 个数字。从梯形 的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶 至底的路径。 规则1:从梯形的顶至底的m条路径互不相交。 规则2:从梯形的顶至底的m条路径仅在数字结点处相交。 规则3:从梯形的顶至底的m条路径允许在数字结点相交或边相交。 2 3 3 4 5 9 10 9 1 1 1 10 1 1 1 1 10 12 1 1 对于给定的数字梯形,分别按照规则1,规则2,和规则3 计算出从梯形的顶至底的m 条路径,使这m条路径经过的数字总和最大。

    Input

    由文件input.txt提供输入数据。文件的第1 行中有2个正整数m和n(m,n<=20),分别 表示数字梯形的第一行有m个数字,共有n 行。接下来的n 行是数字梯形中各行的数字。 第1 行有m个数字,第2 行有m+1 个数字,…。

    Output

    程序运行结束时,将按照规则1,规则2,和规则3 计算出的最大数字总和输出到文件 output.txt中。每行一个最大总和。

    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

    Source

    线性规划与网络流24题

     

    - 思路 -

     还是把一个点一分为二, 一个向上连, 一个向下连, 第一层向上连到源点, 第 n 层向下连到汇点, 两点间的点连边费用为点券.
     对于第一种情况, 所有边容量都是 1 .
     对于第二种情况, 表示同一点的两个点间的边容量扩大到inf, 连向汇点的边也扩到inf.
     对于第三种情况, 把不同点间的边容量也扩到inf.
     求最大费用最大流.
     
     细节见代码.
     

    - 代码 -

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
     
    const int N = 1500;
    const int M = 5000;
    const int inf = 0x3f3f3f3f;
     
    int SP[2][M];
    int V[M], CT[M], NXT[M], TO[M];
    int HD[N], PRE[N], DIS[N], VIS[N];
    int A[50], B[50];
    int ss, tt, sz, m, n, tot;
    queue<int> q;
     
    void add(int x, int y, int c, int z1, int z2, int z3) {
        TO[sz] = y; NXT[sz] = HD[x]; HD[x] = sz;
        CT[sz] = c; V[sz] = z1;
        SP[0][sz] = z2; SP[1][sz++] = z3; //存第2,3种情况的容量.
        TO[sz] = x; NXT[sz] = HD[y]; HD[y] = sz;
        CT[sz] = -c; V[sz] = 0;
        SP[0][sz] = SP[1][sz] = 0; sz ++;
    }
     
    bool spfa() {
        memset(DIS, 0xc0, sizeof (DIS));
        DIS[ss] = 0;
        q.push(ss);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            VIS[u] = 0;
            for (int i = HD[u]; i != -1; i = NXT[i]) {
                int v = TO[i];
                if (V[i] && DIS[v] < DIS[u] + CT[i]) {
                    DIS[v] = DIS[u] + CT[i];
                    PRE[v] = i;
                    if (!VIS[v]) {
                        VIS[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
        return DIS[tt] > 0;
    }
     
    int macmf() {
        int cost = 0;
        while (spfa()) {
            int tmp = inf;
            for (int i = tt; i != ss; i = TO[PRE[i]^1])
                if (tmp > V[PRE[i]]) tmp = V[PRE[i]];
            for (int i = tt; i != ss; i = TO[PRE[i]^1]) {
                V[PRE[i]] -= tmp;
                V[PRE[i]^1] += tmp;
            }
            cost += tmp * DIS[tt];
        }
        return cost;
    }
     
    int main() {
        memset(HD, -1, sizeof (HD));
        scanf("%d%d", &m, &n);
        ss = 0, tt = ++tot;
        int cnt = n * (m + m + n - 1) / 2;
        for (int i = 1, x; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                scanf("%d", &x);
                A[j] = ++tot;
                add(tot, tot + cnt, x, 1, inf, inf);
                if (i == 1) add(ss, tot, 0, 1, 1, 1);
                else {
                    if (i == n) add(tot + cnt, tt, 0, 1, inf, inf); 
                    if (j != 1) add(B[j - 1], tot, 0, 1, 1, inf);
                    if (j != m) add(B[j], tot, 0, 1, 1, inf); //注意这里是B[j]不是B[j+1]
                }
            }
            for (int j = 1; j <= m; ++j)
                B[j] = A[j] + cnt;
            m++;
        }
        printf("%d
    ", macmf());
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < sz; ++j)
                V[j] = SP[i][j];
            printf("%d
    ", macmf());
        }
        return 0;
    }
    
  • 相关阅读:
    hihoCoder #1062 : 最近公共祖先·一
    hihoCoder #1050 : 树中的最长路
    hihoCoder #1049 : 后序遍历
    108 Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树
    107 Binary Tree Level Order Traversal II 二叉树的层次遍历 II
    106 Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
    105 Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树
    104 Maximum Depth of Binary Tree 二叉树的最大深度
    102 Binary Tree Level Order Traversal 二叉树的层次遍历
    101 Symmetric Tree 判断一颗二叉树是否是镜像二叉树
  • 原文地址:https://www.cnblogs.com/Anding-16/p/7427163.html
Copyright © 2011-2022 走看看