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; }
#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; }