题目:传送门
题意
Srwudi 的家是一幢 hh 层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi 改造了一个跳楼机,使得访客可以更方便的上楼。
经过改造,srwudi 的跳楼机可以采用以下四种方式移动:
- 向上移动X层;
- 向上移动Y层;
- 向上移动Z层;
- 回到第一层。
一个月黑风高的大中午,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; }