hdu6071[最短路+解不等式] 2017多校4

求出所有,从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\n", (double)clock() / CLOCKS_PER_SEC );
    dij(2);
    //cout << cnt << endl,cnt=0;
    //printf("%.2f\n", (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\n", ans);
}
int main() {
    scanf("%d", &T);
    while (T--) solve();
    return 0;
}
 

 

posted @ 2017-08-04 23:52 UnderSilence 阅读(...) 评论(...) 编辑 收藏