C. Journey(dp)
先说思路 启示放在后面
dp[i][j]: 从1号点到i号点且经过j个点的最少时间 那么答案就是dp[n][j] (1<=j<=n) 中小于等于T的最大的j值 转移方程很好想 如果有一条从u到v的边 那么dp[v][j] = min(dp[u][j-1]+w) 这里加上min是因为可能有多条到v的边 注意初始化dp数组不能用1e9 必须比1e9大 因为T最大可以达到1e9 至于如何记录路径直接看代码吧
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int N = 5005;
struct node
{
int u,v,w;
}e[N];
int n,m,T;
int dp[N][N],pre[N][N];
stack<int> st;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>T;
for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
memset(dp,0x3f,sizeof dp);
dp[1][1]=0;
int ans;
for(int j=2;j<=n;j++)
{
for(int i=1;i<=m;i++)
{
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
if(dp[u][j-1]+w < dp[v][j])
{
dp[v][j] = dp[u][j-1]+w;
pre[j][v] = u; //关键 u->v 对于每个j只有一个u->v
}
}
if(dp[n][j] <= T) ans=j;
}
cout<<ans<<endl;
int now = n;
while(now)
{
st.push(now);
now = pre[ans][now];
ans--;
}
int f=0;
while(!st.empty())
{
if(f==0) cout<<st.top();
else cout<<" "<<st.top();
st.pop();
f++;
}
}
启示
- memset(dp,0x3f,sizeof dp);//这行代码可以把dp数组初始化为0x3f3f3f3f 一个比1e9略大的值 并且0x3f+0x3f不会超出int的范围
- 这种倒序输出答案的 用std中的stack是不错的选择

浙公网安备 33010602011771号