JZOJ4722. 跳楼机

探讨通过特定移动模式计算跳楼机可达楼层数的方法。利用SPFA算法优化求解过程,避免重复计算,确保高效准确地得出答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

有一幢h层的大楼,有一个跳楼机可以移动,初始时在一楼。
跳楼机可以采用以下四种方式移动:

  1. 向上移动x层
  2. 向上移动y层
  3. 向上移动z层
  4. 回到第一层

给定h,x,y,z,求跳楼机能到达的楼层数。

Data Constraint
h1018  ,  x,y,z105

题解

我们考虑只记向上移动y层和移动z层的方案,然后可以再移动x层多少次是可以计算的。设当前到达了c层,那么这种情况贡献的方案数就是hcx+1,但是这样算会有重复。假如枚举到两个c1,c2满足c1>c2c1c2 (mod x),那么c1的方案在计算c2是就已经算过了。所以我们只要保留较小的那个值。
di表示最小的c满足ci (mod x),那么转移有两种可能:

  • di+yd(i+y)mod x
  • di+zd(i+z)mod x

观察到转移的实质其实与最短路类似。所以SPFA跑一下就好了。最后Ans=hdix+1

SRC

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;

#define N 1000000 + 10
typedef long long ll ;

bool vis[N] ;
int d[10*N] ;
ll Dist[N] ;
int x , y , z ;
ll h , ans ;

void SPFA() {
    memset( Dist , 63 , sizeof(Dist) ) ;
    int i = 0 , j = 1 ;
    d[1] = 1 % x ;
    Dist[1%x] = 1 ;
    while ( i < j ) {
        i ++ ;
        int now = d[i] ;
        int s = (now + y) % x ;
        if ( Dist[now] + y < Dist[s] ) {
            Dist[s] = Dist[now] + y ;
            if ( !vis[s] ) {
                vis[s] = 1 ;
                d[++j] = s ;
            }
        }
        s = (now + z) % x ;
        if ( Dist[now] + z < Dist[s] ) {
            Dist[s] = Dist[now] + z ;
            if ( !vis[s] ) {
                vis[s] = 1 ;
                d[++j] = s ;
            }
        }
        vis[now] = 0 ;
    }
}

int main() {
    scanf( "%lld%d%d%d" , &h , &x , &y , &z ) ;
    SPFA() ;
    for (int i = 0 ; i < x ; i ++ ) {
        if ( Dist[i] > h ) continue ;
        ans += (h - Dist[i]) / x + 1 ;
    }
    printf( "%lld\n" , ans ) ;
    return 0 ;
}

以上.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值