• Vijos 1002 过河 dp + 思维


    https://www.vijos.org/p/1002

    设dp[i]表示跳到了第i个点,需要的最小的步数。

    所以复杂度O(L * T), 不行

    注意到T最大是10, 所以dp[i]最多只由10项递推过来。

    考虑上面的那个情况,如果两个相邻的石头距离大于10,那么其实是没意义的,比如上面那两个空的10的位置,完全是可以省略的。因为它相当于从那个有石子的那10个转移过来。所以只要两个距离大于10的石子,就可以压缩距离是10即可。

    但是这样做的话,有一个大前提,就是你必须保证每个位置都是可达的。否则,比如你只能去到18和19,你就不能把这两个位置压缩成10和11,因为很有可能10和11是不可达的状态,然后你这个石子就永远枚举不了。也破坏了整到题目的题意。

    所以只有保证每个状态都是可达的,然后又是空的位置,才能省略。

    最差情况是s == t,这个时候特判。

    然后就是s + 1 == t,比如9、10的时候,可达的地方是:

    0、9、10、18、19、20、27、28、29、30......观察到大于100后,全部状态都是可达的,所以这个时候就可以压缩了。

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 1e5 + 20;
    int a[maxn], dp[maxn];
    int f[maxn];
    void work() {
        memset(dp, 0x3f, sizeof dp);
        int L, s, t, m;
        scanf("%d%d%d%d", &L, &s, &t, &m);
        for (int i = 1; i <= m; ++i) {
            scanf("%d", f + i);
        }
        sort(f + 1, f + 1 + m);
        int to = 0;
        for (int i = 1; i <= m; ++i) {
            if (f[i] - f[i - 1] > 100) {
                to += 100;
                a[to] = true;
            } else {
                to += f[i] - f[i - 1];
                a[to] = true;
            }
        }
        if (s == t) {
            int ans = 0;
            for (int i = 1; i <= m; ++i) {
                ans += f[i] % s == 0;
            }
            cout << ans << endl;
            return;
        }
        dp[0] = 0;
        for (int i = s; i <= maxn - 20; ++i) {
            int be = max(0, i - t), en = max(0, i - s);
            for (int j = be; j <= en; ++j) {
                dp[i] = min(dp[i], dp[j] + a[i]);
            }
        }
        int ans = inf;
        for (int i = maxn - 20; i <= maxn - 1; ++i) {
            ans = min(ans, dp[i]);
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    AtCoder Grand Contest 001F Wide Swap
    生成函数/母函数入门学习
    树的点分治入门小结
    树链剖分入门小结
    有重复元素的全排列
    二项式界
    二项系数
    排列问题、组合问题
    容斥原理
    P3372 【模板】线段树 1
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7121969.html
Copyright © 2020-2023  润新知