题:https://ac.nowcoder.com/acm/contest/3004/J
分析:
这个题首先先求一遍最短路,这个求最短路的过程可以用flord实现。
接下来类似最长上升子序列,但是显然这个好像不太好优化,考虑暴力m^2转移,由于地图的大小只有200,所以200步以后可以转移到任意位置,用这个性质可以优化m^2->200m。
也就是说每次转移只暴力往前for200个,多余200个以上的时候记录一个前缀max,直接从这个前缀中转移。
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define pb push_back const ll INF=1e18; const int M=1e5+5; struct node{ int pos,t; ll val; }a[M]; ll dp[M]; ll dis[220][220]; bool cmp(node p,node q){ return p.t<q.t; } int main(){ int n,m; ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) if(i==j) dis[i][j]=0; else dis[i][j]=INF; } for(int i=1;i<=m;i++){ int u,v; ll w; cin>>u>>v; dis[u][v]=1; dis[v][u]=1; } for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } int p; cin>>p; for(int i=1;i<=p;i++){ cin>>a[i].t>>a[i].pos>>a[i].val; } sort(a+1,a+1+p,cmp); a[0].pos=1; a[0].t=a[0].val=0; ll maxx=0,ans=0; for(int i=1;i<=p;i++){ if(i>200){ maxx=max(maxx,dp[i-200]); dp[i]=maxx+a[i].val; } else dp[i]=-INF; for(int j=1;j<=200&&i-j>=0;j++){ if(a[i].t-a[i-j].t>=dis[a[i].pos][a[i-j].pos]) dp[i]=max(dp[i],dp[i-j]+a[i].val); } ans=max(ans,dp[i]); } cout<<ans<<endl; return 0; }