• Luogu 1941 飞扬的小鸟


    题目链接:https://www.luogu.org/problemnew/show/P1941

    思路:

    这是一道极好的背包练习题。

    容易地发现,我们可以把上升的过程与有限制的完全背包联系,下降的过程与$01$背包联系。

    因此可以进行分别处理。

    对于上升过程,通过画图,我们可以发现它可以从两种进行转移。

    一种是从前一个位置来跳跃,另一种则是从当前位置转移。

    对于$(i,m)$,我们需要把它在沿途中更新。

    对于下降的情况,我们再输入数据时,先确定一个可穿过的区间,然后枚举$j+a[i-1].y$是否满足条件,然后进行转移,其转移方程与上升时的情况、原理类似。

    然后记得把不能到的地方重新标记。

    最后统计答案即可。

    代码:

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    const int MAXN = 20050;
    const int MAXM = 1050;
    const int INF = 1 << 30;
    using namespace std;
    struct node1 {
        int x, y;
    } a[MAXN];
    struct node2 {
        int p, l, h;
    } b[MAXN];
    int n, m, k, cnt, ans = INF, up[MAXN], down[MAXN], f[MAXN][MAXM];
    bool flag[MAXN];
    int read() {
        int x = 0;
        bool sign = false;
        char alpha = 0;
        while (!isdigit(alpha)) sign |= alpha == '-', alpha = getchar();
        while (isdigit(alpha)) x = (x << 1) + (x << 3) + (alpha ^ 48), alpha = getchar();
        return sign ? -x : x;
    }
    int main() {
        n = read();
        m = read();
        k = read();
        for (int i = 0; i < n; i++) a[i].x = read(), a[i].y = read();
        for (int i = 1; i <= n; i++) up[i] = m + 1;
        for (int i = 1; i <= k; i++) {
            b[i].p = read(), b[i].l = read(), b[i].h = read();
            flag[b[i].p] = true;
            up[b[i].p] = b[i].h;
            down[b[i].p] = b[i].l;
        }
        for (int i = 1; i <= n; i++)
            for (int j = 0; j <= m; j++) f[i][j] = INF;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (j >= a[i - 1].x)
                    f[i][j] = min(f[i][j], min(f[i - 1][j - a[i - 1].x] + 1, f[i][j - a[i - 1].x] + 1));
                if (j == m)
                    for (int l = j - a[i - 1].x; l <= m; l++)
                        f[i][j] = min(f[i][j], min(f[i - 1][l] + 1, f[i][l] + 1));
            }
            for (int j = down[i] + 1; j <= up[i] - 1; j++)
                if (j + a[i - 1].y <= m)
                    f[i][j] = min(f[i][j], f[i - 1][j + a[i - 1].y]);
            for (int j = 1; j <= down[i]; j++) f[i][j] = INF;
            for (int j = up[i]; j <= m; j++) f[i][j] = INF;
        }
        cnt = k;
        for (int i = n; i >= 1; i--) {
            for (int j = down[i] + 1; j <= up[i] - 1; j++)
                if (f[i][j] < INF)
                    ans = min(ans, f[i][j]);
            if (ans != INF)
                break;
            if (up[i] <= m)
                cnt--;
        }
        cnt == k ? (cout << "1" << endl << ans << endl) : (cout << "0" << endl << cnt << endl);
        return 0;
    }
  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/BeyondLimits/p/11160548.html
Copyright © 2020-2023  润新知