zoukankan      html  css  js  c++  java
  • P2045 方格取数加强版 最大费用最大流

    $ color{#0066ff}{ 题目描述 }$

    给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

    (color{#0066ff}{输入格式})

    第一行两个数n,k(1<=n<=50, 0<=k<=10)

    接下来n行,每行n个数,分别表示矩阵的每个格子的数

    (color{#0066ff}{输出格式})

    一个数,为最大和

    (color{#0066ff}{输入样例})

    3 1
    1 2 3
    0 2 1
    1 4 2
    

    (color{#0066ff}{输出样例})

    11
    

    (color{#0066ff}{数据范围与提示})

    每个格子中的数不超过1000

    (color{#0066ff}{题解})

    拆点,矩阵每个元素拆成入点和出点

    入点向出点连容量为1, 权值为点权的边,代表只能选一次

    入点再向出点连容量为inf,权值为0的边,代表之后也能走这个格子,但是无法获得权值

    最大费用最大流即可(这里用了ZKWqwq)

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
        char ch; LL x = 0, f = 1;
        while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
        for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
        return x * f;
    }
    const int inf = 0x7fffffff;
    const int maxn = 1e5 + 10;
    struct node {
        int to, can, dis;
        node *nxt, *rev;
        node(int to = 0, int can = 0, int dis = 0, node *nxt = NULL): to(to), can(can), dis(dis), nxt(nxt) {
            rev = NULL;
        }
    };
    node *head[maxn];
    bool vis[maxn];
    int dis[maxn], mp[100][100];
    int n, k, s, t;
    void add(int from, int to, int can, int dis) {
        head[from] = new node(to, can, dis, head[from]);
    }
    void link(int from, int to, int can, int dis) {
        add(from, to, can, dis);
        add(to, from, 0, -dis);
        head[from]->rev = head[to];
        head[to]->rev = head[from];
    }
    bool spfa() {
        for(int i = s; i <= t; i++) vis[i] = false, dis[i] = -inf;
        std::deque<int> q;
        q.push_back(t);
        dis[t] = 0;
        while(!q.empty()) {
            int tp = q.front(); q.pop_front();
            vis[tp] = false;
            for(node *i = head[tp]; i; i = i->nxt) {
                if(dis[i->to] < dis[tp] - i->dis && i->rev->can) {
                    dis[i->to] = dis[tp] - i->dis;
                    if(!vis[i->to]) {
                        if(!q.empty() && dis[i->to] > dis[q.front()]) q.push_front(i->to);
                        else q.push_back(i->to);
                        vis[i->to] = true;
                    }
                }
            }
        }
        return dis[s] != -inf;
    }
    int dfs(int x, int change) {
        if(x == t || !change) return change;
        int flow = 0, ls;
        vis[x] = true;
        for(node *i = head[x]; i; i = i->nxt) {
            if(!vis[i->to] && dis[i->to] == dis[x] - i->dis && (ls = dfs(i->to, std::min(change, i->can)))) {
                flow += ls;
                change -= ls;
                i->can -= ls;
                i->rev->can += ls;
                if(!change) break;
            }
        }
        return flow;
    }
    int zkw() {
        int cost = 0;
        while(spfa()) {
            vis[t] = true;
            while(vis[t]) {
                for(int i = s; i <= t; i++) vis[i] = false;
                cost += dis[s] * dfs(s, inf);
            }
        }
        return cost;
    }
    
    int id(int x, int y) { return (x - 1) * n + y; }
    
    int main() {
        n = in(), k = in();
        for(int i = 1; i <= n; i++) 
            for(int j = 1; j <= n; j++)
                mp[i][j] = in();
        s = 0, t = 2 * n * n + 1;
    	link(s, id(1, 1), k, 0);
    	link(id(n, n) + n * n, t, k, 0);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++) {
    			if(i + 1 <= n) link(n * n + id(i, j), id(i + 1, j), inf, 0);
    			if(j + 1 <= n) link(n * n + id(i, j), id(i, j + 1), inf, 0);
    			link(id(i, j), n * n + id(i, j), 1, mp[i][j]);
    			link(id(i, j), n * n + id(i, j), inf, 0);
            }
        printf("%d", zkw());
        return 0;
    }
    
  • 相关阅读:
    剑指 Offer 48. 最长不含重复字符的子字符串
    剑指 Offer 47. 礼物的最大价值
    剑指 Offer 42. 连续子数组的最大和
    剑指 Offer 40. 最小的k个数
    剑指 Offer 39. 数组中出现次数超过一半的数字
    剑指 Offer 34. 二叉树中和为某一值的路径
    剑指 Offer 33. 二叉搜索树的后序遍历序列
    java类与对象(属性,方法)的使用
    java--基本数据类型的转换(强制转换)
    java--基本数据类型的转换(自动转换)
  • 原文地址:https://www.cnblogs.com/olinr/p/10478945.html
Copyright © 2011-2022 走看看