zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营3 J 牛牛的宝可梦Go

    https://ac.nowcoder.com/acm/contest/3004/J

    我的思路:

    维护到达每个路口的累计宝可梦战斗力递增序列,同时记录相应时间

    每次转移的时候,枚举每个路口,二分找到时间允许的最靠后的(战斗力最大的)那个来转移

    题解思路:

    一共200个路口,最大距离199,所以抓的上一个宝可梦只需要考虑之前200个即可,再前面的用一个前缀最大值记录

    #include<cstdio>
    #include<algorithm>
     
    using namespace std;
     
    #define N 100001
    #define M 201
     
    int st[M][N],top[M];
    long long w[M][N];
     
    int f[M][M];
    struct node
    {
        int tim,pos,val;
    }e[N];
     
    bool cmp(node p,node q)
    {
        return p.tim<q.tim;
    }
      
    int main()
    {
        int n,m,u,v;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                if(i!=j) f[i][j]=1e9;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            if(u!=v) f[u][v]=f[v][u]=1;
        }
        for(int k=1;k<=n;++k)
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                    f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
        scanf("%d",&m);
        for(int i=1;i<=m;++i) scanf("%d%d%d",&e[i].tim,&e[i].pos,&e[i].val);
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=n;++i) st[i][0]=f[1][i];
        int y,now;
        long long ans=0,mx;
        for(int i=1;i<=m;++i)
        {
            now=e[i].pos;
            mx=0;
            for(int j=1;j<=n;++j)
                if(e[i].tim>=f[now][j])
                {
                    y=upper_bound(st[j],st[j]+top[j]+1,e[i].tim-f[now][j])-st[j]-1;
                    if(y>=0) mx=max(mx,w[j][y]+e[i].val);
                }
            if(mx>w[now][top[now]])
            {
                top[now]++;
                st[now][top[now]]=e[i].tim;
                w[now][top[now]]=mx;
                ans=max(ans,mx);
            }
        }
        printf("%lld",ans);
        return 0;
    }
    View Code
    #include<cstdio>
    #include<algorithm>
     
    using namespace std;
     
    #define N 100001
    #define M 201
     
    long long dp[N];
     
    int f[M][M];
    struct node
    {
        int tim,pos,val;
    }e[N];
     
    bool cmp(node p,node q)
    {
        return p.tim<q.tim;
    }
      
    int main()
    {
        int n,m,u,v;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                if(i!=j) f[i][j]=1e9;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            if(u!=v) f[u][v]=f[v][u]=1;
        }
        for(int k=1;k<=n;++k)
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                    f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
        scanf("%d",&m);
        for(int i=1;i<=m;++i) scanf("%d%d%d",&e[i].tim,&e[i].pos,&e[i].val);
        sort(e+1,e+m+1,cmp);
        long long mx=0,ans=0;
        dp[0]=0;
        e[0].pos=1;
        for(int i=1;i<=m;++i)
        {
            if(i>200) 
            {
                mx=max(mx,dp[i-200]);
                dp[i]=mx+e[i].val;
            }
            dp[i]=-1e15;
            for(int j=1;j<200 && i-j>=0;++j)
                if(f[e[i].pos][e[i-j].pos]<=e[i].tim-e[i-j].tim) dp[i]=max(dp[i],dp[i-j]+e[i].val);
            ans=max(ans,dp[i]);
        }
        printf("%lld",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    多项式大合集
    【题解】Codeforces 961G Partitions
    【题解】Counting D-sets(容斥+欧拉定理)
    【题解】分特产(组合数+容斥)
    【题解】P4247 [清华集训]序列操作(线段树修改DP)
    【题解】没有上司的舞会
    【题解】数字组合(NTT+组合 滑稽)
    【瞎总结】组合模型及其组合意义的阐释
    P2822 组合数问题——巧用前缀和
    P3239 [HNOI2015]亚瑟王——概率DP
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12404760.html
Copyright © 2011-2022 走看看