昨天刚刚做过类似的题,就是用最短路的松弛方式来维护dp数组
/* 考虑一个二元组(t,i) 表示花费t时间,当前处在绿灯的now=t%g秒,处于结点i now!=0,可以扩展点(t+x,j),且now+x<=g now==0,可以扩展点(t+x,j),且x<=g y用一个优先队列维护这个二元组 */ #include<bits/stdc++.h> using namespace std; #define ll long long #define N 2000006 int n,g,r,m,d[N],vis[10005][1005]; int main(){ cin>>n>>m; for(int i=1;i<=m;i++)scanf("%d",&d[i]); cin>>g>>r; priority_queue<pair<int,int> >pq; pq.push(make_pair(0,1)); vis[1][0]=1; int tt=0; long long anss=1e16; while(pq.size()){ ++tt; if(t>=5e6)break; pair<int,int> p=pq.front();pq.pop(); int t=-p.first,u=p.second; if(u==m){ long long ans=1ll*t/g*(g+r)+t%g; anss=min(anss,ans); } int now=t%g; for(int v=u+1;v<=m && now+d[v]-d[u]<=g;v++){ if(!vis[v][now+d[v]-d[u]])vis[v][now+d[v]-d[u]]=1; else continue; pq.push(make_pair(-(t+d[v]-d[u]),v)); } for(int v=u-1;v>=1 && now+d[u]-d[v]<=g;v--){ if(!vis[v][now+d[u]-d[v]])vis[v][now+d[u]-d[v]]=1; else continue; pq.push(make_pair(-(t+d[u]-d[v]),v)); } } if(anss==1e16)puts("-1"); else cout<<anss<<' '; }
当然这题时间卡的比较紧,我们还要优化掉dij的那个log
所以采用01bfs,dis[i][j]表示到第i个点,已经到了绿灯j秒,经过的最少周期数
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<unordered_map> using namespace std; typedef long long LL; typedef unsigned long long ull; const int inf=0x3f3f3f3f; const int N=1e4+100; int n,m,r,g; bool vis[N][1010]; int a[N],dis[N][1010]; struct Node { int pos,step; Node(int pos,int step):pos(pos),step(step){} }; int bfs() { int ans=-1; deque<Node>q; q.push_back(Node(0,0)); vis[0][0]=true; while(q.size()) { Node cur=q.front(); q.pop_front(); if(cur.step==0)//刚等完红灯 { int remain=n-a[cur.pos]; if(remain<=g)//如果能直接从这个安全岛冲到终点 { LL temp=dis[cur.pos][cur.step]*(g+r)+remain; if(ans==-1||temp<ans) ans=temp; } } if(cur.step==g)//需要等红灯 { if(!vis[cur.pos][0]) { dis[cur.pos][0]=dis[cur.pos][g]+1; vis[cur.pos][0]=true; q.push_back(Node(cur.pos,0)); } continue; } if(cur.pos>1)//向前一格 { int pos=cur.pos-1; int step=cur.step+a[cur.pos]-a[pos]; if(step<=g&&!vis[pos][step]) { dis[pos][step]=dis[cur.pos][cur.step]; vis[pos][step]=true; q.push_front(Node(pos,step)); } } if(cur.pos<m)//向后一格 { int pos=cur.pos+1; int step=cur.step+a[pos]-a[cur.pos]; if(step<=g&&!vis[pos][step]) { dis[pos][step]=dis[cur.pos][cur.step]; vis[pos][step]=true; q.push_front(Node(pos,step)); } } } return ans; } int main() { // ios::sync_with_stdio(false); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d",a+i); scanf("%d%d",&g,&r); sort(a+1,a+1+m); printf("%d ",bfs()); return 0; }