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


    「luogu3974」[TJOI2015] 组合数问题

    题目链接

    (Description)

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

    (Solution)

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

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

    (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
    ", f[n][1]);
        }
        return 0;
    }
    
  • 相关阅读:
    [java核心篇02]__内部类
    iOS学习之MVC,MVVM,MVP模式优缺点
    iOS MVC、MVP和MVVM理解
    网络常见的9大命令
    计算机网络基础知识总结
    iOS面试常见问题和知识点汇总
    NSMutableArray 删除可变数组元素
    iOS之集成GoogleMap定位、搜索注意事项
    iOS 13-Sign In with Apple
    Lipo移除ORC架构
  • 原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/11724647.html
Copyright © 2020-2023  润新知