同余最短路(P3403 跳楼机)
同余最短路
前置
給定m個數,這m個數可以重復取,問最大的這m個數不能拼成的數,或者給定一定范圍,范圍里有多少個數是這m個數可以拼成的,對于這種問題我們可以考慮同余最短路的算法。
P3403 跳樓機
同余最短路介紹
首先我們要選擇一個basebasebase作為基底,之后所有的距離就可以描述成a?base+ba * base + ba?base+b。
在這題中我們選定xxx作為base。
dis[i]=valuedis[i] = valuedis[i]=value有如下含義:value≡i(modx)value \equiv i \pmod xvalue≡i(modx),也就是同余的條件下,我們可以到達的最小的樓層,這樣我們剩下的樓層就可以通過+x+ x+x的操作去訪問,所以我們最后的可以到達的樓層也就是∑i=0x?1(h?dis[i])/x+1\sum _{i = 0} ^ {x - 1} (h - dis[i]) / x + 1∑i=0x?1?(h?dis[i])/x+1,這句應該稍加簡單理解一下就好了。
接下來我們考慮如何建邊,顯然有i?>(i+y)%xcost=y,i?>(i+z)%xcost=zi - > (i + y) \% x\ cost = y, i -> (i + z) \% x\ cost = zi?>(i+y)%x?cost=y,i?>(i+z)%x?cost=z。
所以我們可以對所有的x∈[0,x?1]x\in [0, x - 1]x∈[0,x?1],分別同上建立一條邊權為yyy的,一條邊權為zzz的邊。然后再去跑一遍最短路,我們就可以得到所有的disdisdis了。
代碼
/*Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> #define mp make_pair #define pb push_back #define endl '\n'using namespace std;typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii;const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f;inline ll read() {ll f = 1, x = 0;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return f * x; }void print(ll x) {if(x < 10) {putchar(x + 48);return ;}print(x / 10);putchar(x % 10 + 48); }const int N = 1e5 + 10;ll h, dis[N];bool visit[N];vector<pii> G[N];void spfa() {memset(dis, 0x3f, sizeof dis);queue<int> q;q.push(1);dis[1] = 1, visit[1] = 1;while(q.size()) {int temp = q.front();q.pop();visit[temp] = 0;for(pii i : G[temp]) {if(dis[i.first] > dis[temp] + i.second) {dis[i.first] = dis[temp] + i.second;if(!visit[i.first]) {q.push(i.first);visit[i.first] = 1;}}}} }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);h = read();int x = read(), y = read(), z = read();if(x == 1 || y == 1 || z == 1) {//注意如果有一個數為1,必須特判,不然我們跑出來的最短路dis,將會重復計數。printf("%lld\n", h);return 0;}for(int i = 0; i < x; i++) {G[i].pb(mp((i + y) % x, y));G[i].pb(mp((i + z) % x, z));}spfa();ll ans = 0;for(int i = 0; i < x; i++) {if(dis[i] <= h) {ans += (h - dis[i]) / x + 1;}}printf("%lld\n", ans);return 0; }總結
以上是生活随笔為你收集整理的同余最短路(P3403 跳楼机)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C简单瞎搞题(牛客练习赛22)(bits
- 下一篇: 四大传统存储方式利弊一览