LGOJ3403跳楼机

Posted tqr06

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LGOJ3403跳楼机相关的知识,希望对你有一定的参考价值。

一栋楼共有 h 层,有以下操作:
1. 向上移动x层
2. 向上移动y层
3. 向上移动z层
4. 回到第一层
问可以达到的楼层数量

如果令\(f(i)\)表示表示仅通过操作2和操作3能到达的 \(mod\ x=i\) 的最小楼层
那么就有以下方程:
\[f(i+y)=f(i)+y\]
\[f(i+z)=f(i)+z\]
想一想最短路的转移方程
\[f(v)=f(u)+dis(u,v)\]

是不是很像?
所以我们可以建图,把 \(i+y\)\(i+z\) 看作点
\(y,z\)成为权值,跑spfa算出\(f(i)\)

由于 \(f(i)\) 的数量统计时没有使用第一个操作
所以每增加一个 \(x\) ,答案都会相应地增加

注意边界是闭区间,所以答案再+1,即
\[ans+=(h-f(i))/x+1\]

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll h,x,y,z,ans=0;
ll f[100005];
struct Edge

    ll next,to,dis;
edge[200005];
int cnt=0,head[200005];

inline void add_edge(ll from,ll to,ll dis)

    edge[++cnt].next=head[from];
    edge[cnt].to=to;
    edge[cnt].dis=dis;
    head[from]=cnt;


template<class T>inline void read(T &res)

    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;

bool vis[100005];
queue<int> q;
void spfa()

    memset(f,0x3f3f3f3f,sizeof(f));
    memset(vis,0,sizeof(vis));
    q.push(1);
    vis[1]=f[1]=1;
    while(!q.empty())
    
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(register int i=head[u];i;i=edge[i].next)
        
            int v=edge[i].to;
            if(f[v]>f[u]+edge[i].dis)
            
                f[v]=f[u]+edge[i].dis;
                if(!vis[v])
                
                    q.push(v);
                    vis[v]=1;
                
            
        
    


int main()

    read(h);
    read(x);read(y);read(z);
    if(x==1||y==1||z==1)printf("%lld\n",h);return 0;
    for(register int i=0;i<x;++i)
    
        add_edge(i,(i+y)%x,y);
        add_edge(i,(i+z)%x,z);
    
    spfa();
    for(register int i=0;i<x;++i) if(f[i]<=h) ans+=(h-f[i])/x+1;
    printf("%lld\n",ans);
    return 0;

以上是关于LGOJ3403跳楼机的主要内容,如果未能解决你的问题,请参考以下文章

[Luogu3403]跳楼机

洛谷 - P3403 跳楼机(同余最短路)

JZOJ 4722. 跳楼机

[spfa][数论]JZOJ 4722 跳楼机

[spfa] Jzoj P4722 跳楼机

JZOJ_4722. 跳楼机 (Standard IO)