AOJ2427 -- ほそながいところ
問題文: hosonagaitokoro | Aizu Online Judge
こういう系 (適切な方針を選ぶと非常に楽になる系) は結構好きです。以下白文字。
馬車 u が馬車 v (u > v) を抜かす場所 (あるいは抜かさない) を全探索すると、各馬車の出発時刻 x[u] に不等式制約が立つので牛をやる。ただし、同時に同じ場所で追い抜きができないので、ある馬車が同じ場所で 2 回以上追い抜きインシデントに遭遇するのは NG とする。O((n(n-1)/2)^(m+1) * n^3)
という方針でやると全然混乱せず実装も楽に一発 AC 出来てよかった。ソースは続き。
ソースコード(テンプレ略)
Int dist, N, S[8], M, D[8], A[8][8], C[8][8], P[8][8], Q[8], res; void search(int u, int v) { if (u == N) { for (int i = 0; i < N; ++i) { Q[i] = INFLL; for (int j = 0; j < N; ++j) { P[i][j] = INFLL; } } for (int i = 1; i < N; ++i) { chmin(P[i][i - 1], -1LL); for (int j = 0; j < i; ++j) { if (A[i][j] == M) { chmin(P[i][j], dist * (S[i] - S[j])); } else { chmin(P[j][i], D[A[i][j]] * (S[j] - S[i])); chmin(P[i][j], D[A[i][j]] * (S[i] - S[j])); } } } Q[N - 1] = 0; for (int i = 0; i <= N * (N - 1); ++i) { bool cont = false; for (int j = 0; j < N; ++j) { for (int k = 0; k < N; ++k) { if (P[j][k] < INFLL && Q[j] + P[j][k] < Q[k]) { cont = true; Q[k] = Q[j] + P[j][k]; } } } if (i == N * (N - 1) && cont) { return; } } Int t = 0; for (int i = 0; i < N; ++i) { chmax(t, (Q[i] - Q[0]) + dist * S[i]); } chmin(res, t); } else if (u == v) { search(u + 1, 0); } else { for (int i = 0; i <= M; ++i) { A[u][v] = i; ++C[u][i]; ++C[v][i]; if (i == M || max(C[u][i], C[v][i]) <= 1) { search(u, v + 1); } --C[u][i]; --C[v][i]; } } } int main() { while (~scanf("%lld", &dist)) { N = in(); for (int i = 0; i < N; ++i) { S[i] = in(); } M = in(); for (int i = 0; i < M; ++i) { D[i] = in(); } if (N == 1) { printf("%lld\n", S[0] * dist); } else { res = INFLL; memset(C, 0, sizeof(C)); search(1, 0); printf("%lld\n", res); } } return 0; }