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

猜你喜欢

转载自www.cnblogs.com/TheRoadToTheGold/p/12404760.html
今日推荐