• 「luogu3974」[TJOI2015] 组合数问题


    「luogu3974」[TJOI2015] 组合数问题

    题目链接

    \(Description\)

    给一个 \(n \times m \ (1 \leq n, m \leq 10^3)\) 的网格图,每个格子中有好多块财宝;
    每次从左上角出发,只能往右或下走了,每一次经过一个格子至多只能捡走一块财宝;
    问至少要走几次才可能把财宝全捡完。

    \(Solution\)

    把每一个财宝拆成一个点,就是求 \(DAG\) 最小不相交路径覆盖;
    根据 \(Dilworth\) 定理:最小不相交路径覆盖 = 最长反链;
    题目转换为求一个从右上到左下,取出一个最大的任意两点不可达的点集。
    \(f_{i, j}\) 表示以 \((i, j)\) 为左下角的矩形里的最长反链:

    \[f_{i,j} = \max \big\{ f_{i - 1, j + 1} + a_{i,j}, \ \max \{ { f_{i - 1, j}, f_{i, j + 1} } \} \big\} \]

    \(Source\)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    int in() {
        int x = 0; char c = getchar(); bool f = 0;
        while (c < '0' || c > '9')
            f |= c == '-', c = getchar();
        while (c >= '0' && c <= '9')
            x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
        return f ? -x : x;
    }
    template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
    template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
    
    const int N = 1e3 + 5;
    
    int n, m, mp[N][N];
    long long f[N][N];
    
    int main() {
        //freopen("in", "r", stdin);
        int tim = in();
        while (tim--) {
            n = in(), m = in();
            for (int i = 1; i <= n; ++i)
                for (int j = 1; j <= m; ++j)
                    mp[i][j] = in();
            for (int i = 1; i <= n; ++i)
                for (int j = m; j; --j) {
                    f[i][j] = f[i - 1][j + 1] + mp[i][j];
                    chk_max(f[i][j], f[i][j + 1]);
                    chk_max(f[i][j], f[i - 1][j]);
                }
            printf("%lld\n", f[n][1]);
        }
        return 0;
    }
    
  • 相关阅读:
    SQL的高级属性-
    查询
    SQL语句
    CSS的创建样式
    表单部分属性值
    HTML的语法和基本标签
    网页制作与HTML基本结构
    小程序button 去边框
    关于axios跨域带cookie
    Uncaught Error: code length overflow. (1604>1056)
  • 原文地址:https://www.cnblogs.com/15owzLy1/p/11724647.html
Copyright © 2020-2023  润新知