zoukankan      html  css  js  c++  java
  • POJ3422 Kaka's Matrix Travels 【最大费用最大流】

    Kaka's Matrix Travels
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 8006   Accepted: 3204

    Description

    On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking care that the rook moves only to the right or down. Kaka adds the number to SUM in each grid the rook visited, and replaces it with zero. It is not difficult to know the maximum SUM Kaka can obtain for his first travel. Now Kaka is wondering what is the maximum SUM he can obtain after his Kth travel. Note the SUM is accumulative during the K travels.

    Input

    The first line contains two integers N and K (1 ≤ N ≤ 50, 0 ≤ K ≤ 10) described above. The following N lines represents the matrix. You can assume the numbers in the matrix are no more than 1000.

    Output

    The maximum SUM Kaka can obtain after his Kth travel.

    Sample Input

    3 2
    1 2 3
    0 2 1
    1 4 2
    

    Sample Output

    15

    Source

    POJ Monthly--2007.10.06, Huang, Jinsong

    题意:有一个NxN的棋盘,小明从左上角開始走到右下角,仅仅能向右和向下走。每一个落子点都有一个非负整数。小明每次经过一个落子点都会将点的值加到sum上,同一时候该点的值清零。问:假设小明走K次的话sum的最大值是多少。同一个点能够走多次。

    题解:拆点+费用流。走K次表示最大流为K,求sum最大值表示求最大费用。构图时要将点权拆分成边权,比方点X,拆成X到X'有一条容量为1的边。费用为该点原来的值,再在X到X'间加一条边。容量inf,费用0,然后再用X'跟其它点相连。因为是求最大费用。因此每次增广路时SPFA都要向大松弛。


    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #define inf 0x3f3f3f3f
    #define maxN 55
    #define maxn maxN * maxN * 2
    #define maxm maxn * 4
    using std::queue;
    
    int head[maxn], n, k, id;
    struct Node {
        int u, v, c, f, next;
    } E[maxm];
    int dist[maxn], map[maxN][maxN];
    int pre[maxn], source, sink;
    bool vis[maxn];
    
    void addEdge(int u, int v, int c, int f) {
        E[id].u = u; E[id].v = v; E[id].f = f;
        E[id].c = c; E[id].next = head[u];
        head[u] = id++;
        E[id].u = v; E[id].v = u; E[id].f = -f;
        E[id].c = 0; E[id].next = head[v];
        head[v] = id++;
    }
    
    void getMap() {
        memset(head, -1, sizeof(head));
        int i, j, f, pos, down, right; id = 0;
        for(i = 0; i < n; ++i)
            for(j = 0; j < n; ++j) {
                scanf("%d", &map[i][j]);
                pos = i * n + j; right = pos + 1;
                down = pos + n;
                addEdge(pos, pos + n*n, 1, map[i][j]); // 拆点
                addEdge(pos, pos + n*n, inf, 0);
                if(i != n - 1) {
                    addEdge(pos + n*n, down, inf, 0);
                }
                if(j != n - 1) {
                    addEdge(pos + n*n, right, inf, 0);
                }
            }
        source = 2 * n * n; sink = source + 1;
        map[n][0] = map[n][1] = 0;
        addEdge(source, 0, k, 0);
        addEdge(source - 1, sink, k, 0);
    }
    
    bool SPFA(int start, int end) {
        memset(pre, -1, sizeof(pre));
        memset(vis, 0, sizeof(vis));
        memset(dist, -1, sizeof(dist));
        queue<int> Q; Q.push(start);
        int u, v, i; vis[start] = 1; dist[start] = 0;
        while(!Q.empty()) {
            u = Q.front(); Q.pop(); vis[u] = 0;
            for(i = head[u]; i != -1; i = E[i].next) {
                v = E[i].v;
                if(E[i].c && dist[v] < dist[u] + E[i].f) {
                    dist[v] = dist[u] + E[i].f;
                    pre[v] = i;
                    if(!vis[v]) {
                        vis[v] = 1; Q.push(v);
                    }
                }
            }
        }
        return dist[end] != -1;
    }
    
    void solve() {
        int sum = 0, i, u, v, minCut;
        while(SPFA(source, sink)) {
            minCut = inf;
            for(i = pre[sink]; i != -1; i = pre[E[i].u]) {
                if(minCut > E[i].c) minCut = E[i].c;
            }
            sum += minCut * dist[sink];
            for(i = pre[sink]; i != -1; i = pre[E[i].u]) {
                E[i].c -= minCut;
                E[i^1].c += minCut;
            }
        }
        printf("%d
    ", sum);
    }
    
    int main() {
        // freopen("stdin.txt", "r", stdin);
        while(scanf("%d%d", &n, &k) == 2) {
            getMap();
            solve();
        }
        return 0;
    }


  • 相关阅读:
    C++雾中风景16:std::make_index_sequence, 来试一试新的黑魔法吧
    神经网络中的降维和升维方法 (tensorflow & pytorch)
    论文翻译:2020_Residual Acoustic Echo Suppression Based On Efficient Multi-Task Convolutional Neural Network
    论文翻译:2018_Deep Learning for Acoustic Echo Cancellation in Noisy and Double-Talk Scenarios
    十分钟入门Apollo
    SpringSecurity实现OAuth2+JWT
    实现Vue的多页签组件
    原生redis命令
    .NET Core学习笔记(8)——Entity Framework Core之Database First
    函数极限的计算_计算机程序化实现的理论基础
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5244199.html
Copyright © 2011-2022 走看看