某时刻某地点出现val(最短路+dp)

题: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;
}
View Code
原文地址:https://www.cnblogs.com/starve/p/12287658.html