P3403 跳楼机

/*
ax+by+cz 有多少种可能
单变量思想 将 x单独独立出来 
-> -y+ -z 可以由x部分代替
->dp[i]  %x==i 的最小楼层 dp[i+y]=dp[i]+y 但是推到方向不是单向 可能由更小的推导出来
->spfa 

x==1||----- ans=h
(h-dp[])/h+1 -> dp[]<=h

*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
//#include<queue>
//#include<vector>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=1e5+10 ;

int x,y,z;
ll h,ans,dis[maxn];
int head[maxn],to[maxn<<1],nxt[maxn<<1],w[maxn<<1],tot;
int vis[maxn];

void add(int a,int b,int val){
    to[++tot]=b,nxt[tot]=head[a],head[a]=tot,w[tot]=val;
}

void spfa()
{
    memset(dis,0x3f3f3f3f,sizeof(dis));
    queue<int> q; q.push(1);dis[1]=1;vis[1]=1;
    
    while(!q.empty())
    {
        int u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];i;i=nxt[i])
        {
            int v=to[i];
            if(dis[v]>dis[u]+w[i])
            {
                dis[v]=dis[u]+w[i];
                if(vis[v]==0) q.push(v),vis[v]=1;
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin>>h>>x>>y>>z;
    if(x==1||y==1||z==1) {cout<<h<<'\n';return 0; }
    for(int i=0;i<x;i++){
        add(i,(i+y)%x,y);
        add(i,(i+z)%x,z);
    }
    
    spfa();
    
    for(int i=0;i<x;i++)
        if(dis[i]<=h)
            ans+=(h-dis[i]-1+1)/x+1;

    
    cout<<ans<<endl;
    
    return 0;
}

 

posted @ 2023-09-17 16:08  JMXZ  阅读(13)  评论(0)    收藏  举报