You have N guards in a line each with a demand of coins. You can skip paying a guard only if his demand is less than what you have totally paid before reaching him. Find the least number of coins you spend to cross all guards.
I think its a DP problem but can't come up with a formula. Another approach would be to binary search on the answer, but how do I verify if a number of coins is a possible answer?
This is indeed a dynamic programming problem.
Consider the function f(i, j), which is true (one) if there is an assignment of the first i guards which give you cost j. You can arrange function f(i, j) in a table of size n x S, where S is the sum of all the guards demand.
Let us denote d_i as the demand of guard i.
You can easily compute the column f(i+1) if you have f(i) by simply scanning f(i) and assigning f(i+1, j + d_i) as one if f(i + 1, j) is true and j < d_i, or f(i + 1, j) if j >= d_i.
This runs in O(nS) time and O(S) space (you only need to keep two columns per time), which is only pseudopolynomial (and quadratic-like if demands are somehow bounded and does not grow with n).
A common trick to reduce the complexity of a DP problem is to get an upper bound B on the value of the optimal solution. This way, you can prune unnecessary rows, obtaining a time complexity of O(nB) (well, even S is an upper-bound, but a very naïve one).
It turns out that, in our case, B = 2M, where M is the maximum demand of a guard.
In fact, consider the function best_assignment(i), which gives you the minimum amount of coins to pass the first i guards.
Let j be the guard with demand M. If best_assignment(j - 1) > M, then obviously the best assignment for the whole sequence is pay the guards for the best assignment of the first j-1 guards and skip the others, otherwise the upper-bound is given by best_assignment(j - 1) + M < 2M.
But how much best_assignment(j - 1) can be in the first case? It cannot be more than 2M.
This can be proven by contradiction. Let us suppose that best_assignment(j - 1) > 2M. In this assignment, the guard j-1 is paid? No, because 2M - d_{j-1} > d_{j-1}, thus it does not need to be paid. The same argument holds for j-2, j-3, ... 1, thus no guard is paid, which is absurd unless M = 0 (a very naïve case to be checked).
Since the upper-bound is proved to be 2M, the DP illustrated above with n columns and 2M rows solves the problem, with time complexity O(nM) and space complexity O(M).
function crossCost(amtPaidAlready, curIdx, demands){
//base case: we are at the end of the line
if (curIdx >= demands.size()){
return amtPaidAlready;
}
costIfWePay = crossCost(amtPaidAlready + demands[curIdx], curIdx+1, demands);
//can we skip paying the guard?
if (demands[curIdx] < amtPaidAlready){
costIfWeDontPay = crossCost(amtPaidAlready, curIdx+1, demands);
return min(costIfWePay, costIfWeDontPay);
}
//can't skip paying
else{
return costIfWePay;
}
}
This runs in O(2^N) time because it may call itself twice per execution. It's a good candidate for memoization, because it is a pure function with no side effects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With