题意
(啊好难总结复制了)
去学校只有两种方式,坐公交车和步行,牛牛去学校是一条直线,这条直线上总共有n个车站,车站之间的距离都是相等的,每个车站只有一种公交车ai,每个公交车只在对应的公交站停车,第i种公交车过一站的时间需要ti,并且公交车是单向行驶,只能从左到到右,走路可以任意走,然而牛牛自己步行走一站需要的时间为T,恰好牛牛家和学校都在某一个站点,分别为s和t,问最少需要多少时间牛牛才能到学校?
题解
建图,存在两种情况
- 通过步行到达,任意两点均可,但为了效率,仅对相邻两点填边(双向边)即可
- 通过公交车到达,对每个站点记录此站点公交车的上一站,若存在则填边(单向边)。
建好图直接进行dijkstra求最短路即可code
#include <bits/stdc++.h>
#define reg register
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define inf 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
#define e exp(1.0)
#define ios ios::sync_with_stdio(false)
#define rep(i,l,r) for(int i=(l);i<(r);i++)
using namespace std;
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
int head[maxn],tot;
struct Edge{
int v,w;
int nxt;
bool operator<(const Edge& x)const{
return w < x.w;
}
}edges[maxn << 1];
int busT[maxn];
int a[maxn];
int pre[maxn];
int mp[maxn];
bool vis[maxn];
ll dist[maxn];
void addedge(int u,int v,int w)
{
edges[tot] = {v,w,head[u]};
head[u] = tot++;
}
void dij(int s)
{
priority_queue<pii,vector<pii>,greater<> > pq;
pq.push({0,s});
while(!pq.empty()){
pii hd = pq.top();pq.pop();
if(vis[hd.second]) continue;
vis[hd.second] = 1;
for(int i = head[hd.second];i != -1;i = edges[i].nxt){
int to = edges[i].v;
int cost = edges[i].w;
if(dist[to] > hd.first + cost){
dist[to] = hd.first + cost;
pq.push({dist[to],to});
}
}
}
}
int main()
{
fill(dist,dist + maxn,inf);
memset(head,-1,sizeof(head));
tot = 0;
int n,m,s,t,T;
cin>>n>>m>>s>>t>>T;
for(int i = 1;i <= m;++i) cin>>busT[i];
for(int i = 1;i <= n;++i) cin>>a[i];
for(int i = 1;i <= n;++i){
if(!mp[a[i]]) mp[a[i]] = i;
else{
pre[i] = mp[a[i]];
mp[a[i]] = i;
}
}
for(int i = n;i >= 2;--i){
addedge(i,i-1,T);
addedge(i-1,i,T);
}
for(int i = 1;i <= n;++i){
if(pre[i]){
addedge(pre[i],i,busT[a[i]]);
}
}
dij(s);
printf("%lld\n",dist[t]);
return 0;
} 求大佬解释为啥dp不能过啊..
dp代码
#include <bits/stdc++.h>
#define reg register
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define inf 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
#define e exp(1.0)
#define ios ios::sync_with_stdio(false)
#define rep(i,l,r) for(int i=(l);i<(r);i++)
using namespace std;
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
ll n,m,s,t,T;
ll busT[maxn];
ll stop[maxn];
ll pre[maxn];
ll dp[maxn];
int mp[maxn];
int main()
{
memset(pre,-1,sizeof(pre));
cin>>m>>n>>s>>t>>T;
for(int i = 1;i <= n;++i) cin>>busT[i];
for(int i = 1;i <= m;++i) cin>>stop[i];
for(int i = 1;i <= m;++i){
if(mp[stop[i]]){
pre[i] = mp[stop[i]];
}
else mp[stop[i]] = i;
}
dp[s] = 0;
for(int i = s-1;i >= 1;--i){ //起点前面的站只能通过步行到达
dp[i] = dp[i+1] + T;
}
for(int i = s+1;i <= m;++i){ //起点后面的站转移,从上一车站或从上一站步行到达
if(pre[i] == -1) dp[i] = dp[i-1] + T;
else dp[i] = min(dp[i-1] + T,dp[pre[i]] + busT[stop[i]]);
}
printf("%lld\n",dp[t]);
return 0;
} 
京公网安备 11010502036488号