第一次遇到这种数学题转化为图论的题目,与我一开始的想法相同,将其中一个变量与另外两个变量分离开来,便于处理。由于以前一直认为SPFA会被卡,所以使用了堆优化的Dijkstra,结果超时了,为什么呢?因为我们构造出来的图是一张很稀疏的图,在这种图上Dijkstra与SPFA比较是比较劣的。由于图是我们自己构造的,并不是什么专门用来卡SPFA的网格图等等,所以可以使用SPFA,一定不会超时。(打破了我不要用SPFA的认识233)
另外,还是要注意边界情况,当x为1的时候并不存在模x意义下能够跳到1楼的情况,因此在这种情况下dis[1]是不会被纳入计算的,答案就变成了0,但其实是题中所给的h。
#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,r,l) for(int i=(r);i>=(l);i--)
using namespace std;
typedef long long ll;
const int N=1e5+10;
int x,y,z;
int to[N*2],nxt[N*2],w[N*2],head[N],len;
ll h,ans,dis[N];
inline void addedge(int a,int b,int ww){ nxt[++len]=head[a]; head[a]=len; to[len]=b; w[len]=ww; }
queue<int> q;
bool inq[N];
int main(){
cin>>h>>x>>y>>z;
if(x==1){
cout<<h;
return 0;
}
rep(i,0,x-1) addedge(i,(i+y)%x,y),addedge(i,(i+z)%x,z);
memset(dis,0x3f,sizeof(dis)); dis[1]=1;
q.push(1); inq[1]=true;
while(!q.empty()){
int h=q.front(); q.pop(); inq[h]=false;
for(int i=head[h];i!=0;i=nxt[i]){
if(dis[h]+w[i]<dis[to[i]]){
dis[to[i]]=dis[h]+w[i];
if(!inq[to[i]]){
inq[to[i]]=true;
q.push(to[i]);
}
}
}
}
rep(i,0,x-1) if(dis[i]<=h) ans+=(h-dis[i])/x+1;
cout<<ans;
return 0;
}