求出所有,从2走到x所需的花费在对 t = 2*min(d1,2, d2,3) 模运算下, 所有剩余系的最短路即可(把一个点拆成 t 个点, 每个点代表一种剩余系), 知道了所有剩余系就可以凑出答案。
dis[ 2 ][ 0 ] 到 dis[ 2 ][ t - 1 ] 代表的即为对 t 取模的所有剩余系的最短路 。
假设任意路线走回 2 点的话费是 K0 , 那么必定存在一种 K0+ t 花费(在min(d1,2, d2,3) 来回跑一次)的方案, 那么就是用最短路解不等式了,有点线性规划的感觉。
/*hdu6071[最短路+同余优化] 2017多校4*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL, int> P; int G[5][5]; int T, n, a, b, c, d; LL cnt = 0; LL t, k, dis[5][60005]; void init() { memset(dis, 0x3f, sizeof(dis)); memset(G, 0, sizeof(G)); } priority_queue<P, vector<P>, greater<P> >pq; void dij(int u) { while (!pq.empty()) pq.pop(); pq.push(P(0LL, u)); while (!pq.empty()) { LL w = pq.top().first; int v = pq.top().second; pq.pop(); if (w > dis[v][w % t]) continue; for (int i = -1; i < 3; i += 2) { int nxtp = (((v + i) % 4) == 0 ? 4 : (v + i) % 4); LL nxtw = w + G[v][nxtp] ; if (dis[nxtp][nxtw % t] > nxtw) { dis[nxtp][nxtw % t] = nxtw; //cnt++; pq.push(P(nxtw, nxtp)); } } } } void solve() { init(); LL ans = 0x3f3f3f3f3f3f3f3f; scanf("%lld%d%d%d%d", &k, &a, &b, &c, &d); G[1][2] = G[2][1] = a; G[2][3] = G[3][2] = b; G[3][4] = G[4][3] = c; G[4][1] = G[1][4] = d; t = 2 * min(G[2][1], G[2][3]); //printf("%.2f ", (double)clock() / CLOCKS_PER_SEC ); dij(2); //cout << cnt << endl,cnt=0; //printf("%.2f ", (double)clock() / CLOCKS_PER_SEC ); for (int i = 0; i < t; i++) { if (k <= dis[2][i]) { ans = min(dis[2][i], ans); } else { ans = min(ans, dis[2][i] + ((k - dis[2][i] + t - 1) / t) * t); } } printf("%lld ", ans); } int main() { scanf("%d", &T); while (T--) solve(); return 0; }