Page **1** of **1**

### 11187 - Water Crisis

Posted: **Tue Mar 06, 2007 2:36 pm**

by **little joey**

Isn't this an exponential time complexity brute forcer?

I had to pull quite a number of tricks to get within the time limit, and I see most respected colleague-solvers getting times above 1 second. Even so, there are some people getting very fast times. Did I miss something?

Posted: **Tue Mar 06, 2007 3:07 pm**

by **fpavetic**

can you share those tricks?

Posted: **Tue Mar 06, 2007 3:10 pm**

by **krijger**

I used the following DP-approach: The problem basically comes down to splitting a set of objects into three sets (the three trucks) in such a way that the maximum of the weights of the numbers a set is minimal.

This can be solved using a three dimensional dp, where dp*[j][k] denotes if it is possible to split the first i numbers in such a way that the sum of weights in the first set is j and in the second set is k (and the third set is therefore fixed).*

This gives an O(KT^2) algorithm, where K (<=200) is the total demand and T is the total time we hame (T<=60*20=1200). Because we have to ride back to the office, all numbers will be even, so we can reduce T by 2 => our algorithm takes maximal 200*600*600=72.000.000 operations, which unfortunately gives TLE.

We can optimize our algorithm a bit by only considering j<=k and only looping till the sum so far etc, but it still gives TLE. What we need is that if there are 4 (our more) objects in our set with the same weight, then at least one of the trucks has to do at least 2 of these objects, so we can combine 2 of these objects into an object with duplicate size. This reduction can be applied until all weights have maximum frequency three, after which we can run our algorithm with a lower K.

This last optimization was enough to give me AC in 7.658 seconds.

Posted: **Tue Mar 06, 2007 4:16 pm**

by **little joey**

That last trick is very clever (reminds me of another problem dealing with marbles, but i can't remember the problem title). I thought of the DP solution, but rejected it in an early stage, because of the too high memory consumption (which was premature, I see now).

My solution is an (intrinsically worse) O(3^K) backtracker, where at each level one of the K loads is assigned to one of the three trucks. Some of the tricks I used:

- You know the best possible time at forehand, so once you find a solution with this time, you can stop the search; if this time is too big, you don't have to search at all. It's not guaranteed that this works in all cases, but if it does, it's a time saver.

- Sort the loads by time required. Once a truck is not assigned a load of a specific duration, he will never be assigned a load of that same duration. There are only max. 19 different durations, so this is a major time saver.

- The first load is always assigned to the first truck. The second truck has to be assigned a load before the third truck gets an assignment. This reduces the search time by a factor 6.

My runtime is 0.1 seconds, but I fear my program would time out on horror-cases, although I haven't tried. Still there are times below 0.01 seconds, and I wonder how that is possible.

Posted: **Tue Mar 06, 2007 7:19 pm**

by **sclo**

I had another similar 3 dimentional dp.

dp*[j][k] = denotes the minimum time to finish the last i jobs (as time elapsed after the first truck leaves), where the second truck not available for the first j mins, and that the third truck is not available for the first j+k mins. Here, we can assume that we can just treat the 3 trucks as identical, and we sort the truck according to the when they are first available.*

We can use the same trick of dividing all the times by 2, since all times are even. Furthermore we can guarantee that 0<= j,k < 100, since we know that no jobs requires more than 100 mins. (Using the krijger's trick to reduce K mentioned above would violate this requirement, but the bound can be modified).

Overall, the runtime is O(200*100*100) = 2 mil, 5.727sec which is quite ok, considering the fact that I didn't do any other optimizations.

Posted: **Wed Mar 07, 2007 1:00 am**

by **Noldorin**

Quite similar to a problem named Bookcase in this years NWERC, but a bit more time hungry. For this one as the matrix can be very empty, so you can save in a array the places in the matrix that are correct, and sorting the length of the costs of the water delivery to not apply the same cost over and over again to the same valid configuration (If you have to make 4 deliveries with cost 5, only apply the second iteration to the points generated by the first, and so on). A little annoying having to adjust the algorithm constant costs to fit in time but i like that kind of problems.

Posted: **Wed Mar 07, 2007 2:16 am**

by **erictwpt**

sclo wrote:What is interesting is that the fastest 4 times are all people from Taiwan. I would think that their solutions are either the same or similar. I wouldn't be happy if all they did was to print the solutions. Usually only something close to a constant time solution or linear time solution can give runtimes that fast.

Because we are all classmates made in Taiwan, and discussed this problem together.

Actually I just did a simple backtracking.

Binary search the limit, and using the same idea from USACO problem Fence Rails (but with just 3 trucks).

Posted: **Wed Mar 07, 2007 2:54 am**

by **s000015**

Our solutions are similar with little joey's,

but I used an additional trick(my English is too poor to

describe it precisely), and we binary-search the min. time:

Code: Select all

```
a = infinity
i = best possible time
j = worst possible time
while(i<=j)
{
k = (i+j) / 2
if(All loads can be assigned)
a=min(res,k)
j=k-1
else
i=k+1
}
print res
```

Posted: **Wed Mar 07, 2007 9:35 am**

by **Per**

Noldorin wrote:Quite similar to a problem named Bookcase in this years NWERC, but a bit more time hungry.

Yeah, my solution was almost the same as my solution for Bookcase, with the same optimisations: keep track of which entries of the matrix are filled, prune away entries which can never improve upon the best solution found so far, and remove symmetries between states, e.g. state

*[j][k] is equivalent to **[k][j] (and similarly for the third truck though I only did it for the first two).*

That gave around 7 secs, but using krijgers second optimisation would probably decrease it a lot more.

Posted: **Wed Mar 07, 2007 10:04 am**

by **Per**

Per wrote:That gave around 7 secs, but using krijgers second optimisation would probably decrease it a lot more.

Yes, it did. Doing the full symmetry optimisations as well, it ended up on roughly 1 second.

Posted: **Sat Mar 24, 2007 9:21 am**

by **..**

little joey wrote:That last trick is very clever (reminds me of another problem dealing with marbles, but i can't remember the problem title). I thought of the DP solution, but rejected it in an early stage, because of the too high memory consumption (which was premature, I see now).

I think the problem you talk about is 711 "Dividing up".

Posted: **Sat Mar 24, 2007 9:24 pm**

by **little joey**

.. wrote:
I think the problem you talk about is 711 "Dividing up".

Yes it is

Everything well with you, Lawrence? I noticed you're working man now.

Posted: **Sun Mar 25, 2007 9:55 am**

by **windows2k**

Hello.

I tried to solve the problem with the thought mentioned above.

But get wa all the time.

Could someone give some input/output for me?

Thanks