• [Luogu2045] 方格取数加强版


    题目描述

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

    输入输出格式

    输入格式:

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

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

    输出格式:

    一个数,为最大和

    输入输出样例

    输入样例#1: 复制
    3 1
    1 2 3
    0 2 1
    1 4 2
    输出样例#1: 复制
    11

    说明

    每个格子中的数不超过1000


    拆点, 费用流。


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    #define reg register
    
    inline char gc()
    {
        static const int BS = 1 << 22;
        static unsigned char buf[BS], *st, *ed;
        if (st == ed) ed = buf + fread(st = buf, 1, BS, stdin);
        return st == ed ? EOF : *st++;
    }
    #define gc getchar
    inline int read()
    {
        int res=0;char ch=gc();bool fu=0;
        while(!isdigit(ch)){if(ch=='-')fu=1;ch=gc();}
        while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=gc();
        return fu?-res:res;
    }
    #define N 5010
    #define M 200010
    int n, k;
    int a[55][55];
    int S, T;
    int ans;
    
    struct edge {
        int nxt, to, flow, val;
    }ed[M];
    int head[N], cnt = 1;
    inline void add(int x, int y, int z, int c)
    {
        ed[++cnt] = (edge){head[x], y, z, c};
        head[x] = cnt;
        ed[++cnt] = (edge){head[y], x, 0, -c};
        head[y] = cnt;
    }
    
    inline int id(int i, int j, int k) {
        return (i - 1) * n + j + k * n * n;
    }
    int incf[N], dis[N], pre[N];
    bool ex[N];
    
    inline bool spfa()
    {
        memset(dis, 0xcf, sizeof dis);
        memset(ex, 0, sizeof ex);
        queue <int> q;
        q.push(S);
        dis[S] = 0;
        incf[S] = 1 << 25;
        while(!q.empty())
        {
            int x = q.front();q.pop();
            ex[x] = 0;
            for (reg int i = head[x] ; i ; i = ed[i].nxt)
            {
                if (ed[i].flow) {
                    int to = ed[i].to;
                    if (dis[to] < dis[x] + ed[i].val) {
                        dis[to] = dis[x] + ed[i].val;
                        pre[to] = i;
                        incf[to] = min(incf[x], ed[i].flow);
                        if (!ex[to]) ex[to] = 1, q.push(to);
                    }
                }
            }
        }
        return dis[T] != 0xcfcfcfcf;
    }
    
    inline void update()
    {
        int x = T;
        while(x != S)
        {
            int i = pre[x];
            ed[i].flow -= incf[T];
            ed[i^1].flow += incf[T];
            x = ed[i^1].to;
        }
        ans += dis[T] * incf[T];
    }
    
    int main()
    {
        n = read(), k = read();
        for (reg int i = 1 ; i <= n ; i ++)
            for (reg int j = 1 ; j <= n ; j ++)
                a[i][j] = read();
        S = 1, T = 2 * n * n;
        for (reg int i = 1 ; i <= n ; i ++)
            for (reg int j = 1 ; j <= n ; j ++) {
                add(id(i, j, 0), id(i, j, 1), 1, a[i][j]);
                add(id(i, j, 0), id(i, j, 1), k - 1, 0);
                if (j + 1 <= n) add(id(i, j, 1), id(i, j + 1, 0), k, 0);
                if (i + 1 <= n) add(id(i, j, 1), id(i + 1, j, 0), k, 0);
            }
        while(spfa()) update();
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    js Object.freeze()
    js Object.seal()
    js数字千分位,三种写法,,拿走。。。
    nodejs mongoose连接mongodb报错,command find requires authentication
    nodejs express 服务代理
    容器监控之cadvisor
    kubernetes 集群卸载清理
    解决目录太大-建立软链接
    与运算(&)、或运算(|)、异或运算(^)
    jpa中将查询的字段返回为Map键值对类型
  • 原文地址:https://www.cnblogs.com/BriMon/p/9559418.html
Copyright © 2020-2023  润新知