S. Bridging the Gap
46th Annual hosted by ICPC World Championship AASTMT Problem S Bridging the Gap Time limit...
Problem Statement
Formatted from the contest statement text, with sample tests broken out into copyable blocks.
46th Annual hosted by
ICPC World
Championship AASTMT
Problem S
Bridging the Gap
Time limit: 4 seconds
A group of walkers arrives at a river in the night. They
want to cross a bridge, which can hold a limited number
of walkers at a time. The walkers have just one torch,
which needs to be used when crossing the bridge. Each
walker takes a certain time to cross; a group crossing
together must walk at the slowest walker’s pace. What
is the shortest time it takes for all walkers to cross the
bridge?
For example, Sample Input 1 assumes the bridge can
hold 2 walkers at a time and there are 4 walkers with
crossing times 1 minute, 2 minutes, 5 minutes and 10
A bridge with low capacity
minutes, respectively. The shortest time of 17 minutes
can be achieved by the following sequence of crossings.
First, the two fastest walkers cross in 2 minutes. Second, the fastest walker crosses back in 1 minute.
Third, the two slowest walkers cross in 10 minutes. Fourth, the second-fastest walker crosses back in 2
minutes. Fifth, the two fastest walkers cross in 2 minutes.Input
The first line of input contains two integers n and c, where n (2 ≤ n ≤ 104 ) is the number of walkers, and c (2 ≤ c ≤ 104 ) is the number of walkers the bridge can hold at a time. Then follows a line containing n integers t1 , . . . , tn (1 ≤ ti ≤ 109 for all i). The ith walker takes time ti to cross.
Output
Output the minimum total time it takes for the entire group to cross the bridge.
Sample Tests
4 2
1 2 10 5 17 4 6
1 2 10 5 10 Editorial
The solution write-up is rendered from the LaTeX source, with equations kept live through MathJax.
Key Observations
Sort the walkers by time: \[ t_1 \le t_2 \le \cdots \le t_n. \] In an optimal solution, every backward crossing is made by exactly one walker: if several walkers came back together, keeping only the fastest of them is never worse.
Before the last trip, a forward crossing consists of some number of currently slowest walkers that are meant to stay on the far side, plus some number of fastest walkers that will later return one by one. Using any non-fast walker as a future returner is dominated by using a faster one.
This suggests a dynamic program over:
how many slow walkers have already been moved permanently;
how many future one-person return trips have already been ``paid for'' by sending fast helpers across earlier.
Besides mixed trips that move slow walkers, we may also take a fast-only package: send $h+1$ fastest walkers across, planning for $h$ of them to return later. This produces $h$ future return credits and costs \[ t_{h+1} + \sum_{i=1}^{h} t_i. \] These package costs can be precomputed with an unbounded knapsack.
Algorithm
Sort the crossing times increasingly.
Precompute
credit_cost[x]= minimum extra cost of fast-only packages that create exactly $x$ future return credits.Let
dp[done][credit]be the minimum cost after thedoneslowest walkers have been moved permanently, withcreditnet prepaid returns available.From state
(done, credit), choose how many fast helpers accompany the next block of slow walkers. Ifhelpers = h, then:the crossing moves $c-h$ of the remaining slow walkers permanently;
its time contribution is the slowest moved walker plus $\sum_{i=1}^{h} t_i$, because those $h$ fast helpers will later return individually;
the net number of credits changes by $h-1$, since every non-final forward crossing needs one return trip.
The DP only keeps the credit range that can still matter, which reduces the number of reachable states to $O(n^2/c)$.
After all slow walkers have been transferred, add enough fast-only packages to settle any remaining credit deficit and take the best final cost. enumerate
Correctness Proof
We prove that the algorithm returns the correct answer.
Lemma 1.
There exists an optimal solution in which every backward crossing consists of a single walker.
Proof.
Suppose some backward crossing contains several walkers. Replacing it by only the fastest walker from that group still returns the torch to the near side and cannot increase the time of that crossing. The other walkers can simply remain on the far side. Repeating this transformation yields an optimal solution with only single-person returns. □
Lemma 2.
There exists an optimal solution in which every forward crossing is either:
a group of the currently slowest remaining walkers, possibly together with some of the globally fastest walkers that will later return; or
a fast-only package.
Proof.
By Lemma 1, future returners always cross back alone. If a forward trip contains a walker who will later return, replacing that walker by a faster not-yet-used walker can only decrease future return costs and cannot increase the forward trip time. Thus temporary helpers may be assumed to be chosen from the globally fastest walkers.
The walkers intended to stay permanently on the far side may then be taken in decreasing order of speed: if two permanent walkers are transferred in the opposite order, swapping them does not worsen any trip, because only the slowest walker in each forward group matters. Hence some optimal solution has exactly the stated structure. □
Lemma 3.
Every schedule of the form described in Lemma 2 is represented by a unique path in the dynamic program, and every DP path corresponds to a valid schedule of that form.
Proof.
The state records precisely the two quantities needed to continue optimally: how many slow walkers have already been transferred permanently, and how many prepaid one-person returns are still available. Each transition chooses the number of fast helpers on the next forward trip, which uniquely determines how many slow walkers are moved, what time is added, and how the credit balance changes. Conversely, any schedule of the structured form yields exactly those state changes. Therefore the DP and the structured schedules are in one-to-one correspondence. □
Theorem.
The algorithm outputs the minimum total crossing time.
Proof.
By Lemmas 1 and 2, some optimal solution has the structured form modeled by the DP. By Lemma 3, the DP explores exactly all such solutions and computes their exact total cost, including the cheapest possible fast-only packages needed to settle the final credit balance. Therefore the minimum value produced by the DP is the true optimum. □
Complexity Analysis
The pruned state space has size $O(n^2/c)$, and each state has $O(c)$ outgoing transitions, so the main DP runs in $O(n^2)$ time. The fast-only package preprocessing is also $O(n^2)$ in the worst case. The memory usage is $O(n^2/c)$.
Implementation Notes
The code stores only the credit range that can still matter for a given
done, which is why each DP row has a different width.If $c \ge n$, everybody can cross together immediately and the answer is simply the slowest walker's time.
Code
C++ solution used for this page.
#include <bits/stdc++.h>
using namespace std;
namespace {
void solve() {
int n, c;
cin >> n >> c;
vector<long long> t(n);
for (int i = 0; i < n; ++i) {
cin >> t[i];
}
sort(t.begin(), t.end());
if (c >= n) {
cout << t.back() << '\n';
return;
}
const long long INF = (1LL << 62);
vector<long long> fast_prefix(n + 1, 0);
for (int i = 0; i < n; ++i) {
fast_prefix[i + 1] = fast_prefix[i] + t[i];
}
// credit_cost[x]: minimum cost of "fast-only" trips that produce x future return credits.
vector<long long> credit_cost(n, INF);
credit_cost[0] = 0;
for (int helpers = 1; helpers < c && helpers < n; ++helpers) {
long long package_cost = t[helpers] + fast_prefix[helpers + 1];
for (int have = helpers; have < n; ++have) {
credit_cost[have] = min(credit_cost[have], credit_cost[have - helpers] + package_cost);
}
}
vector<int> min_credit(n + 1), max_credit(n + 1);
vector<vector<long long>> dp(n + 1);
for (int done = 0; done <= n; ++done) {
min_credit[done] = -(done / c) - (done == n ? 1 : 0);
max_credit[done] = (n - done + c - 1) / c - 1;
dp[done].assign(max_credit[done] - min_credit[done] + 1, INF);
}
dp[0][-min_credit[0]] = 0;
for (int done = 0; done < n; ++done) {
for (int idx = 0; idx < static_cast<int>(dp[done].size()); ++idx) {
long long current = dp[done][idx];
if (current >= INF) {
continue;
}
// If producing more credits separately would dominate this state, skip it.
if (idx > 0 && current - dp[done][0] >= credit_cost[idx]) {
continue;
}
int credit = min_credit[done] + idx;
int upper = min(n, done + c);
int extra = -1;
for (int next = upper; next > done; --next, ++extra) {
int next_credit = credit + extra;
if (next_credit > max_credit[next]) {
break;
}
int helpers = extra + 1;
long long transition_cost = t[n - 1 - done] + fast_prefix[helpers];
int next_idx = next_credit - min_credit[next];
dp[next][next_idx] = min(dp[next][next_idx], current + transition_cost);
}
}
}
long long answer = INF;
for (int credit = min_credit[n]; credit <= -1; ++credit) {
int idx = credit - min_credit[n];
answer = min(answer, dp[n][idx] + credit_cost[-1 - credit]);
}
cout << answer << '\n';
}
} // namespace
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
Source Files and Assets
Raw files are still available here when you want the original TeX, C++, or statement assets.
Show raw files
competitive_programming/icpc/2022/S-bridging-the-gap/solution.texC++ implementationcompetitive_programming/icpc/2022/S-bridging-the-gap/solution.cppStatement textcompetitive_programming/icpc/2022/S-bridging-the-gap/statement.txtStatement PDFcompetitive_programming/icpc/2022/S-bridging-the-gap/statement.pdfMetadatacompetitive_programming/icpc/2022/S-bridging-the-gap/meta.jsonYear packetcompetitive_programming/icpc/2022/contest_problems.pdf