洛谷 P3403 跳楼机

题目:传送门

题意

Srwudi 的家是一幢 hh 层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi 改造了一个跳楼机,使得访客可以更方便的上楼。

经过改造,srwudi 的跳楼机可以采用以下四种方式移动:

  1. 向上移动X层
  2. 向上移动Y层
  3. 向上移动Z层
  4. 回到第一层。

一个月黑风高的大中午,DJL 来到了 srwudi 的家,现在他在 srwudi 家的第一层,碰巧跳楼机也在第一层。DJL 想知道,他可以乘坐跳楼机前往的楼层数。

输入格式

第一行一个整数 hh,表示摩天大楼的层数。

第二行三个正整数,分别表示题目中的 x, y, z

输出格式

一行一个整数,表示 DJL 可以到达的楼层数。

 

 思路

洛谷题解

同余最短路总结

 

#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
#define fir first
#define sec second
using namespace std;

const int N = 1e6 + 5;

LL h, x, y, z, f[N];
bool vis[N];
int tot, v[N * 2], nx[N * 2], E[N * 2], head[N];

void add(int x, int y, int z) {
    v[++tot] = y;
    nx[tot] = head[x];
    head[x] = tot;
    E[tot] = z;
}

void spfa() {
    mem(f, 0x3f3f3f3f);
    mem(vis, 0);
    queue < int > Q;
    vis[1] = 1;
    f[1] = 1;
    Q.push(1);

    while(!Q.empty()) {
        int x = Q.front(); Q.pop();
        vis[x] = 0;
        for(int i = head[x]; i ; i = nx[i]) {
            int y = v[i];
            if(f[y] > f[x] + E[i]) {
                f[y] = f[x] + E[i];
                if(!vis[y]) {
                    Q.push(y);
                    vis[y] = 1;
                }
            }
        }
    }

}

int main() {

    cin >> h >> x >> y >> z;

    if(x == 1 || y == 1 || z == 1) {
        cout << h << endl;
        return 0;
    }

    LL ans = 0LL;

    rep(i, 0, x - 1) {
        add(i, (i + y) % x, y);
        add(i, (i + z) % x, z);
    }

    spfa();

    rep(i, 0, x - 1) {
        if(f[i] <= h) {
            ans += (h - f[i]) / x + 1;
        }
    }

    cout << ans << endl;

    return 0;
}

 

posted on 2020-03-31 19:19  Willems  阅读(146)  评论(0编辑  收藏  举报

导航