• 「LibreOJ NOIP Round #1」旅游路线


    「LibreOJ NOIP Round #1」旅游路线


    题目链接

    做法:

    1. 首先肯定要预处理些东西,来使单词询问达到(o(logn))或者(o(1))的复杂度,又因为距离这个东西的范围太大,我们考虑预处理一些费用相关的东西。
    2. 考虑(dp[s][j])表示从s出发花费j元,走的最长的距离,如果求出了这个东西,显然距离随费用单调递增,直接在(dp[s])内二分即可。
    3. 可以列出方程:(dp[s][j] = max(dp[t][j-p[s]]+dis[s][t])), (dis[s][t])表示从s到t,在s加一次油走到t最长经过的距离。
    4. 考虑如何计算(dis[s][t]),用(dis[s][t][C])表示从s到t用不超过C的油最长的距离,直接可以folyd求出答案,但是显然会tle,于是可以采用倍增 floyd 的方法预处理数 (dis[s][t][1,2,4,8...]) 即预先计算 (dis[s][t][k]) 表示从 s 到 t 初始油量为 (2^k) 能走的最长距离,然后就可以对于每个起点,合并出它的答案。注意在预处理时不用考虑油量的限制。

    深刻的感受到了要注意细节,这份时间爆炸的代码换个头文件都能tle。。。恳请知道原因的大佬赐教。

    #include <bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    typedef long long ll;
    const int N = 110;
    const int inf = 0x3f3f3f3f;
    inline int read() {
        char c=getchar(); int x=0,f=1;
        while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    using namespace std;
    int n,m,C,T,p[N],c[N];
    
    int dis[17][N][N], dp[N][N*N];
    void init_dis() {
        rep(s,1,16) {
            memcpy(dis[s],dis[s-1],sizeof(dis[s]));
            rep(k,1,n)rep(i,1,n)if(dis[s-1][i][k]!=-1)rep(j,1,n)if(dis[s-1][k][j]!=-1){
                dis[s][i][j]=max(dis[s][i][j],dis[s-1][i][k]+dis[s-1][k][j]);
            }
        }
    }
    int d[N][N],ans[N][N],tmp[17][N][N];
    void getdis(int s) {
        memset(ans,-1,sizeof(ans));
        rep(i,1,n)ans[i][i]=0;
        memset(tmp,-1,sizeof(tmp));
        rep(x,0,16)if(min(c[s],C)&(1<<x)){
            rep(i,1,n)tmp[x][i][i] = 0;
            rep(k,1,n)rep(i,1,n)if(ans[i][k]!=-1)rep(j,1,n)if(dis[x][k][j]!=-1){
                tmp[x][i][j] = max(tmp[x][i][j],ans[i][k]+dis[x][k][j]);
            }
            rep(i,1,n)rep(j,1,n)ans[i][j]=tmp[x][i][j];
        }
        rep(i,1,n) d[s][i] = ans[s][i];
    }
    void init() {
        init_dis();
        rep(i,1,n)getdis(i);
        rep(j,0,n*n)rep(s,1,n)rep(t,1,n)if(j>=p[s]&&d[s][t]!=-1){
            dp[s][j] = max(dp[s][j],dp[t][j-p[s]]+d[s][t]);
        }
    }
    int main() {
        n = read(), m =read(), C = read(), T=read();
        rep(i,1,n) p[i]=read(),c[i]=read();
        int x,y,l;
        memset(dis,-1,sizeof(dis));
        rep(i,1,n)rep(s,0,16)dis[s][i][i]=0;
        rep(i,1,m) x=read(),y=read(),dis[0][x][y]=read();
        init();
        while(T--) {
            int s,q,d;
            s=read(),q=read(),d=read();
            int cs = lower_bound(dp[s],dp[s]+1+n*n,d) - dp[s];
            if(dp[s][cs]>=d&&q>=cs&&cs<=n*n)printf("%d
    ",q-cs);
            else puts("-1");
        }
        return 0;
    }
    
    
  • 相关阅读:
    51Nod1355 斐波那契的最小公倍数
    Topcoder CyclesNumber 和 ARC96E Everything on It
    CF1236F Alice and the Cactus
    Projecteuler522 Hilbert's Blackout
    Projecteuler584 Birthday Problem Revisited
    CF1187F Expected Square Beauty
    BZOJ3451 Normal 和 CF235D Graph Game
    CF1153F Serval and Bonus Problem
    CTSC2006 歌唱王国
    SDOI2012 走迷宫 和 Gym100591D Fox Rocks
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/9432047.html
Copyright © 2020-2023  润新知