Monday, January 3, 2011

Sails (IOI 2007 Problem)

The problem roughly goes: You have a ship with N<=100,000 flagpoles, and each flagpole has an integer height up to 100,000. Each flag can only occupy a height of the flagpole at integer heights. Because the ship should be as aerodynamic as possible, air resistance comes into play. For each flag (don't question the question), it contributes a drag of X Newtons, where X is the number of flags behind it (w.r.t. direction of movement) flying at the same height. Your task is to write a program to determine the minimum amount of drag induced by the flags in total given the height and number of flags on each flagpole.

Here is my proposed algorithm: subject to flaws major and minor:

We make a few random observations that I'm not too sure where they appear in the solution, but let's just list them down first:

1) Total drag = summation x(x-1)/2, where x is the number of flags at each height.
1.1) It doesn't matter what order the flagpoles are arranged in.

2) There exists an optimal solution where the number of flags in each height is non-decreasing as the height gets lower.
Proof: Consider an optimal solution (if it exists) where two consecutive heights are such that the higher height has more flags, then the flags can be shifted down (by Pigeonhole Principle or something, because on the same pole there will exist space for the flags to move down)

3) The objective is to try to spread flags out as far as possible.
"Proof": 3+5>4+4 (by 1 Newton of drag), since well, can't be bothered to explain this.

4) Assuming a/b>c/d, a,b>c,d>0,0 (improvised notation ftw), then (a-c)/(b-d)>c/d.

Proposed Solution Part 1: Definitions
-------------------------------------
Define the highest level of the highest flagpole to have height 1, the second highest level to be 2 and so on, until n.

Define g(i) to be the maximum number of flags you can fly at equal to or higher than the level i.

Define f(j,k)= |g(j)-g(k)/(k-j)| (modulus function ftw).

Proposed Solution Part 2: Calculating g(i)
------------------------------------------
Raise all flags to the maximum. The number of flags at or above height i is now g(i).

To calculate all g(i) in O(N) time, we let the flags at each flagpole by represented by a range (after being raised to the maximum).

The sum of the total length of all parts of all ranges above i is then g(i).

Hence, at the start of each range, we add 1 to an array, and minus 1 after the end of each range. (ie a[0]=0, a[1]=a[0]+number of ranges starting at 1 - number of ranges ending at 0)

g(i) is then the sum of a[0]+a[1]+...+a[i] (or something like that).

Proposed Solution Part 3: The Idea
----------------------------------
Since we wish to spread out the flags among heights evenly, we will try to see whether we can do this 100% efficient. As it turns out, we cannot, because the higher levels will not fit as many flags.

So, we will probably wish to stuff as many flags into the higher levels as possible before moving on to the lower levels.

Say for the highest 6 levels we can fit 5, 14, 14, 16, 17, 18 flags respectively. Then clearly the most optimal solution involves putting 3 flags in each level (assuming there are a lot of flags past the 6th level).

After that, we realise we have reduced the problem, but the condition "(assuming there are a lot of flags past the 6th level)" is a bit iffy, so let's formalise it.

If g(k)/k is minimal among all k from 1 to n, then:
1. The heights above k can have either floor(g(k)/k) or ceiling (g(k)/k) flags.
2. That is the most optimal way of arranging the flags.

Hence, if we can find the minimal g(i)/i, we can reduce the problem.

Proposed Solution Part 4: The Problem
-------------------------------------
If the i that minimises g(i)/i is say, 1, then the reduced problem will have different g(i)/i, since the maximal number of flags above a certain level j in the reduced problem is actually equivalent to |f(i,j)*(i-j)| (stupid definitions). Or I think I should say, f(i,j) is not equal to f(0,j). Yep. That makes more sense. Hence the next minimal f(i,j) might not be the minimal f(0,j). Which means that we have to recalculate everything, which is a lot too slow (O(n^2)).

Proposed Solution Part 5: The Win
---------------------------------
We shall pretend we are stupid (slightly) to solve the problem.

At each height, if f(i, i+1) is more than the previous minimum f(a,i), then we plonk it into a list of minimums. (Like, if say g(3)/3 is the true minimum value of g(i)/i, then f(3,4) may be the minimum value of f(3,i) .

If f(i, i+1) is less than the previous minimum f(a,i), then it must be true (by Observation 4) that f(a,i+1)
After this mess, we now know the minimum g(i)/i. We also know the minimum g(i)/i in the reduced problem, the doubly-reduced problem and so on. Hence, we can calculate the minimum drag the flags add to the ship.

Sunday, January 2, 2011

Chess Match

FORMAT WXF
RED meeeep ; 1219 ;;
BLACK fishballwhite ; 1069 ;;
RESULT 1-0
DATE 2011-01-02 10:45:41
EVENT KGP Game ; 10m+0s
START{
1. C2.5 h2+3 2. P7+1 c2.1 3. H8+7 r1.2
4. R9+1 r2+6 5. E7+9 c8.5 6. H2+3 c1+4
7. R9.6 r2.3 8. R6+1 c1.5 9. H3+5 c5+4
10. A4+5 a6+5 11. C8+4 e7+5 12. R1.2 h8+7
13. R2+7 r9.7 14. P7+1 e5+3 15. R6+4 r3+1
16. R6.7 r3.1 17. R7+1 e+-5 18. C8.3 h7-6
19. C3-2 r1-1 20. K5.4 r7+4 21. C5.7 r7.6
22. A5+4 r6+3 23. K4.5 e3+1 24. C3.8 r1.2
25. C8+3 e5-3 26. C8+1 e3+5 27. R7.5 r2.3
28. C8+1 e1-3 29. C7+7 r3-6 30. R5.8 r6-1
31. R2.7 r3.2 32. R8+2 c5-2 33. R8-3 r6.5
34. K5.4 r5.6 35. K4.5 h6+8 36. R8.5 r6.5
37. K5.4 r5.6 38. K4.5 h8+6 39. R7-3 r6.7
40. R7.2 r7.5 41. K5.4 k5.6 42. R2+5 k6+1
43. R5.3 r5.6 44. K4.5 h6+8 45. R2-1 }END

Feeseeks Quest ion

The story goes like this. A person (Let's call him Suicy, since he is feeling suicidal.) wants to get knocked down by a car. Therefore, He wants to run onto the road and get knocked down by a car. Currently, he is standing A units away from the road, and a car is X units away from that point. This is better illustrated in the picture below.


<--------------X------------>
C
______________________________________________________
^ |
| |
| | (A)
| |
| |
S


In the diagram above (I hope all the spacings work out fine), C represents the car, while S represents Suicy. The car will travel towards the right at constant speed, while Suicy can travel in any direction at constant speed too. However, the car always travels K times as fast as Suicy. So Suicy is lazy. He only wants to start moving at the latest possible moment. He wants to find the minimal X such that he will still be able to move in such a way that he will be able to crash into the car.

Just an example. Suppose Suicy just travels head-on. That means that he moves in the direction shown by the arrow in the picture above. Then X must be at least K*A. If not, Suicy will not hit the car. Obviously, that's not the optimal solution (Because WOODHEAD wants to suan your brain =P), so you need to think of the optimal solution.

In case you are wondering, OBVIOUSLY THE CAR TRAVELS FASTER THAN YOU (Note, that means K > 1)

PS: I noticed that I can write code here. Allow me to amuse myself.
P^2S: Edited out the nonsense.