• D. Bananas in a Microwave dp + 思维


    D. Bananas in a Microwave dp + 思维

    题目大意:

    一开始 (k = 0) ,然后你有两种操作:

    • (Type1:t_i=1,x_i,y_i) ,选择一个 (a_i) ,满足 (0leq a_ileq y_i) ,然后对 (k) 进行下列操作 (a_i) 次,(k = left lceil (k+x_i) ight ceil)
    • (Type2:t_i=2,x_i,y_i) 选择一个 (a_i) ,满足 (0leq a_ileq y_i) ,然后对 (k) 进行下列操作 (a_i) 次,(k = left lceil (k*x_i) ight ceil)

    注意:(x_i) 是一个浮点数

    问:经过最少多少次操作,最后 (k) 会变成 (j(1leq jleq m)) ,输出步数最少的次数,如果不能,那么输出 -1

    题解:

    这个题目还是满巧妙的,很好的一个思维题。

    • 首先,很容易可以想到一个 (O(N*M^2)) 这个复杂度的方法。
    • 但是,显然这个复杂度太高了,是因为每一个点的访问次数有 (N*M)
    • 那么如果减少访问次数呢?
    • 如果: (t,x,y=1,5,10)(k=10) ,那么接下来 (k = 15,20,...,55,60) ,假设 40之前以及被访问过,那么还需要访问40吗?
    • 其实是不需要的,因为 (40) 被访问过,那么他的操作一定在这个之前,暂时还没有被访问,那么 (40) 之后一定会进行 (t,x,y=1,5,10) 这个操作,那么 (k = 40,45,...,90) ,所以连带着,上面40之后的所有数都不需要重新访问了。
    • 这样的话,其实每一个数最多只会被访问 (N)
    • 因为每次产生的新的数都会被保留下来,继续访问,如果访问到一个之前已经存下来的数,就不需要保留,因为之前往后转移时会覆盖这个结果。

    最后感觉好像没有说的太明白,可以仔细看看 (CF) 的题解,非常好的一个题目,题解的代码也写的非常的漂亮。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    const int base = 1e5;
    typedef long long ll;
    
    typedef pair<int,int>pii;
    queue<pii>que;
    
    struct node{
        ll x;
        int t,y;
    }e[maxn];
    
    int ans[maxn];
    bool is_seen[maxn];
    
    inline ll Ceil(ll x,ll y){
        return (x + y - 1) / y;
    }
    
    auto cal(int t,ll &val,ll x) {
        if (t == 1) val += Ceil(x,base);
        else val = Ceil(val*x,base);
    }
    
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
    
        for (int i = 1; i <= n; i++) scanf("%d%lld%d", &e[i].t, &e[i].x, &e[i].y);
    
        memset(ans, -1, sizeof(ans));
        ans[0] = 0;
        is_seen[0] = true;
    
        que.push(pii(0, 0));
    
        while (!que.empty()) {
            auto k = que.front().first;
            auto time = que.front().second;
    
            que.pop(), time++;
    
            if (time > n) break;
    
            auto t = e[time].t;
            auto x = e[time].x;
            auto y = e[time].y;
    
            ll val = k;
            for (int i = 1; i <= y; i++) {
                cal(t, val, x);
    
                if (val > m) break;
                if (is_seen[val]) break;
    
                is_seen[val] = true;
                ans[val] = time;
                que.push(pii(val, time));
            }
            que.push(pii(k, time));
        }
        for (int i = 1; i <= m; i++) printf("%d ", ans[i]);
        printf("
    ");
    }
    
  • 相关阅读:
    【树形dp】Find Metal Mineral
    【树形dp】Apple Tree
    【状压dp】Islands and Bridges
    【状压dp】Travelling
    【状压dp】Most Powerful
    【线段树】Mayor's posters
    【线段树】I Hate It
    【线段树】Atlantis
    【线段树】校门外的树
    【并查集】银河英雄传说
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14606860.html
Copyright © 2020-2023  润新知