Блог пользователя JuanMata

Автор JuanMata, 11 лет назад, По-английски

Tomorrow will take place the Qualification Round of Google Code Jam 2014.
Contest will start 14 hours from now. Note that the contest duration has been extended by 2 hours, so now it will be 27 hours long! :)
Registration for the round has already started, and will be open until end of contest.

Wish all participants good luck in advancing to Round 1. You must score atleast 25 points to advance.

We can discuss the problems here after contest!

  • Проголосовать: нравится
  • +53
  • Проголосовать: не нравится

»
11 лет назад, # |
Rev. 3   Проголосовать: нравится -13 Проголосовать: не нравится

so, this time there were no hard problems.

problem B: ternary search over the number of cookie farms

problem C: boring greedy implementation

problem D:

Sort two arrays.

Game of war: iterate Ken's array from left to right. For each block, try to find the block with lower weight in Naomi's array. Remove two blocks.

Deceitful war: iterate Naomi's array from left to right. For each block, try to find the block with lower weight in Ken's array. Remove two blocks.

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится +58 Проголосовать: не нравится

    There was no need even for ternary search in B; my solution was plain linear, adding farms one-by-one if the next farm would speed up getting to the goal number of cookies.

    • »
      »
      »
      11 лет назад, # ^ |
      Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

      i just used a simple recursion to solve B:

      def solve(r, ub):
      	if x/r > ub:
      		return ub
      	return c/r + solve(r+f, x/r-c/r)
      
      print solve(2, x/2)
      

      here, r is the current rate of generation of cookies and ub is the upper bound of what the function can return (returning anything above that is useless because answer can be reduced by not buying more farms).

      • »
        »
        »
        »
        11 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        How can this code give correct solution for 30.0 1.0 2.0

        x/2.0 = 1.0
        ub = 1.0
        

        I can't understand the logic for recurrsion. Can you help?

        • »
          »
          »
          »
          »
          11 лет назад, # ^ |
          Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

          think of it as kind of a binary tree, with each node having left subtree as a single node, and right subtree as similar to current tree.

          so, solve(r) will have two options:

          • left child assumes that he buys no more farms, so answer is just x/r.
          • right child assumes that he buys one farm. so he has to spend some more time getting back c cookies, but now he has faster r. therefore answer in this case is c/r + solve(r+f).

          now, it only makes sense to use the right child if it yields x cookies faster than left child. for this we require x/r <= c/r + solve(r+f). so we add an extra parameter ub (upper bound on function's return value) and assign ub for the right child as x/r - c/r.
          therefore we get the formula that i posted above.

          hope u understood. if not, tell me which part i need to explain more.

          • »
            »
            »
            »
            »
            »
            11 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Thanks. I'm not getting what ub is exactly doing. Sorry.

            • »
              »
              »
              »
              »
              »
              »
              11 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              it just makes sure that infinite recursion is prevented.
              because using ub allows us to stop recursing when buying more farms wont be useful.

              • »
                »
                »
                »
                »
                »
                »
                »
                11 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                How do you decide the upper bound.?

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  11 лет назад, # ^ |
                  Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

                  if i choose not to buy any more farms, then i will need x/r time to get x cookies. so now i need to make sure time after buying extra farm doesnt exceed this.
                  since c/r time has been used to generate cookies to buy the farm, remaining time is x/r - c/r, which is the upper bound after recursing.

                  EDIT: initially ub will be x/2, as this time can be achieved by not buying even a single farm.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  11 лет назад, # ^ |
                  Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

                  Thank u.! Chelsea fan and BITS, guess we have something in common.:) Which year btw ? I am in 1st.

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      I solved it using the same idea , no need for ternary search

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится +4 Проголосовать: не нравится

    Can you explain the approach for minesweeper? Couldn't get that done. Thanks!

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      my approach was to find the solution in the form of at most 3 connected rectangles X × Y, X1 × 1, 1 × Y1 such that X·Y + X1 + Y1 = R·C - M ,

      where X1 ≤ X, Y1 ≤ Y and (X, X1, Y, Y1) ≠ 1.

      Example:

      4 4 3
      
      X = 3; Y = 3; X1 = 2; Y1 = 2
      
      BB**
      AAA*
      AAAC
      AAAC
      
    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится +7 Проголосовать: не нравится

      If R = 1 or C = 1, it's clear that we can just make the last M cells contain mines.

      Next, there's a special case of M = RC - 1; if M < RC - 1, the field we click on mustn't neighbor mines.

      You can always get +1 free space (without mines) by cutting off concave corners (a mine neighboring 3 free spaces). By doing so, you get a rectangle a × b from f connected free cells, eventually — that means you can get any number of free cells from f to ab.

      The smallest f (that you could get a given a × b rectangle from) is clearly achieved by making a path 2 cells thick along 2 sides of the field and next to a corner, and it's f = 2a + 2b - 4, so it suffices to find some a, b such that 2(a + b - 2) ≤ RC - M ≤ ab, cut off that space next to a corner (a - 1 and b - 1 cells not neighboring any others, along a vertical and a horizontal side) and then remove mines from as many cells from that a × b rectangle as necessary. Example:

      R C M
      4 5 9
      

      for example x = 3, y = 4

      ....*
      ....*
      ..***
      *****
      

      and remove 1 more mine

      ....*
      ....*
      ...**
      *****
      
      • »
        »
        »
        »
        11 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        can you explain with less math jargon plz? I want to know the logic in few sentences if that is possible. forgive my noobness in pure mathematics.

        • »
          »
          »
          »
          »
          11 лет назад, # ^ |
            Проголосовать: нравится +3 Проголосовать: не нравится

          I could make the explanation very long, or too short to explain anything. This is about the best I could do (also, I haven't slept this night). Try to compare your own ideas with mine, look at the examples, etc. Something that helps you understand...

    • »
      »
      »
      11 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +8 Проголосовать: не нравится

      My solution:

      1) R = 1 or C = 1 or M = R·C - 1 as Xellos described.

      2) Try to fill the rectangle (r - 2) × (c - 2) ([0..r - 3] × [0..c - 3]) line by line (fill the the row 0 and all cells [0..c - 3] then the row 1 and etc.).

      3) If you have no remained mines, then you are done.

      4) If the number of remained mines is odd then we try to steal the mine at (r - 3, c - 3) and now the number of remained mines is even.

      5) Now we consider all the rows and columns which have 2 free cells. And fill them by putting 2 mines into those rows and columns.

      If at the end we have remained mines or we couldn't steal mine at step 4 when we need it, then it's Impossible.

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится

      My solution:

      1. R = 1 or C = 1 or M = R C — 1 as Xellos described.
      2. M = 0
      3. (R = 2 or C = 2) and M % 2 == 1 and M != R C — 1 -> Impossible
      4. Let's count free cells, not mines. So, we need RC — M cells. Let's click in a corner. Now we have 4 revealed cells. Then recursively try open new cells while count of revealed is less than needed. Less words, more code:
      void dfs(i, j, current_field, revealed)
           if revealed == M - RC
                 answer <- current_field
           temp <- count of closed adjacent cells
           if temp == 0 or revealed + temp > M - RC
                 return
           current_field <- current_field with revealed adjacent cells
           for dx : -1..1
                 for dy : -1..1
                        dfs(i + dx, j + dy, current_field, revealed + temp)
      

      When I was coding it, I thought that it's bruteforce and works very slow. But execution time of 134 large tests was about 1 second.

      But I can't prove the fact that if solution exists, we can find it, clicking in a corner

    • »
      »
      »
      11 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      My approach. Place bombs to the cells at the shorter side of the remaining rectangle. The only corner case is if number of remaining bombs equal to the (shorter_side_size — 1). In this case we have to place (shorter_side_size — 2) bombs for this side and leave 1 bomb to next iteration.

      Example:
      5 rows 7 columns 28 bombs
      Step 1. Place 5 bomb to 1 column. (remaining rectangle after this step 5x6)
      Step 2. Place 5 bomb to 2 column. (remaining rectangle after this step 5x5)
      Step 3. Place 5 bomb to 3 column. (remaining rectangle after this step 4x5)
      Step 4. Place 5 bomb to 1 row. (remaining rectangle after this step 4x4)
      Step 5. Place 4 bomb to 4 column. (remaining rectangle after this step 3x4)
      Step 6. Place 4 bomb to 2 row. (remaining rectangle after this step 3x3)
      Done.
      
  • »
    »
    11 лет назад, # ^ |
    Rev. 12   Проголосовать: нравится 0 Проголосовать: не нравится

    I understand the strategy of Ken in normal War game, but get confused in Deceitful War. If I was right, then in normal War game, for each value of Naomi, Ken will always find the smallest value that still bigger than Naomi's value. For example, if Naomi give 4 and Ken have 2, 3, 7, 10 then he give 7 and win 1 point. However, in Deceitful War, I don't see this strategy can gives him only 1 point in the last testcase i.e. gives Naomi 8 points. Could you explain which part I was wrong ?

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      If Naomy gives 4 but says that he gives any block with mass > 10, Ken will think that he must play the smallest possible block because he loses anyway. Then he will give 2 and Naomi will win since 4 > 2 .

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

      Basically, Naomi can make Ken play the blocks in the order that's the most advantageous for her.

      She could pick her lightest i blocks, make each of them just a little bit lighter than each of Ken's heaviest i blocks, and thus make him play these blocks (scoring i points). Then, she could pick her N - i heaviest blocks, play them from lightest to heaviest, which will make Ken play his N - i lightest blocks also from lightest to heaviest, making Naomi score N - i points. (Of course, this strategy doesn't have to be possible for some i, but it can be shown that if it isn't, then the answer isn't N - i.)

    • »
      »
      »
      11 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

      Sorted blocks:

      ['0.186', '0.300', '0.389', '0.557', '0.832', '0.899', '0.907', '0.959', '0.992']

      ['0.215', '0.271', '0.341', '0.458', '0.520', '0.521', '0.700', '0.728', '0.916']

      Firstly, take Naomi's blocks which are less than Ken's ones. In our case — 0.186. Naomi know that she won't win this point, but she does not say the real value, because she wants to destroy the heaviest possible Ken's block — 0.916. For example, she can say 0.915, but the value does not matter in this problem. Ken get 1 point, but lose the biggest block.

      Secondly, take the next Naomi's block — 0.300. Note there is Ken's block that are less that Naomi's one — 0.215. Naomi says the value which is heavier that all of Ken's values — 0.729 (again, exact value does not matter). Ken see that he won't win this point, so he wants to lose the smallest block — 0.215. 0.215 < 0.300 — this point goes to Naomi. The next pair will be 0.389 > 0.271 and so on. The last pair will be 0.992 > 0.728. 8 pairs — 8 points.

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится +18 Проголосовать: не нравится

    It's easy to prove in B that optimal answer is N = [X/C — 2/F]. Because X <= 100000, C >= 1, we can only consider all n <= 100000 by line and it wiil be correct solution.

  • »
    »
    11 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +11 Проголосовать: не нравится

    My accepted solution for deceitful war was :-

    Case #x: y z

    Here, in order to find y and z,

    int y = deceitful(naomi, ken);

    int z = N - deceitful(ken, naomi);

    Here, in order to find the score if naomi played game of war optimally, I considered that Ken played deceitful war.

    If you read the rules, Ken also knew the weight of Naomi's block before his chance. Using this, we can say that Ken too played deceitful war game

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится +8 Проголосовать: не нравится

    Wtf, why is there so many negative votes?

»
11 лет назад, # |
Rev. 2   Проголосовать: нравится +9 Проголосовать: не нравится

Problem D is awesome. Let's order all 2N blocks by weight and mark them with +1 if the block belongs to Naomi and with -1 if the block belongs to Ken. Then: 1. The result of War game doesn't depend on Naomi's strategy and is equal to the maximum sum of the suffixes of the array. 2. The result of Deceitful War is equal to N minus the maximum sum of the prefixes of the array.

»
11 лет назад, # |
Rev. 8   Проголосовать: нравится +3 Проголосовать: не нравится

My C-Small Solution was pretty funny.

I figure out there is 225 different input at all, And how about precomputing them?

I used a Brute-Force for precomputing with O(2^RC), RC<=25 for each input, it takes about 1 minute to compute all of them. Then i put the result of this as a part of my final code.

And in final solution i just do a O(RC) to print the answers.

UPD : The picture below show a part of my code to avoid misunderstanding, i don't check states, i found them all before

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится

    Why any precomputing, when brute force works fast enough at all test cases? :)

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      I thought i could hack that code with T=230 and for each R=5 C=5 M=22 ( Should Check 2^25 permutation for each 230 testcases ).

      Also we could do Memorization, But with precomputing i could trust my code will output less than 1 second.

      And also precomputing helps me finding bugs in my two wrong submissions ;)

      • »
        »
        »
        »
        11 лет назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится

        That's not how GCJ tests work. If you want to check whether your code's correct with just 1 test file, that file should contain many different test cases. Also, a lot of them would probably be rather small.

        You know, your code can take minutes to produce the output...

        • »
          »
          »
          »
          »
          11 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

          Yes Surely, I just calculate the worst worst case of Brute-Force.

          My precomputings has been run in my oun computer, in something like this


          for(r=1;r<=5;r++) for(c=1;c<=5;c++) for(m=1;m<=r*c;m++) for(k=0;k<(1<<(r*c));k++){ if(check(k,r,c,m)){ cout<<"Per["<<r<<"]["<<c<<"]["<<m<<"]="<<k<<";"<<endl; break; } }

          and i only put output of this as a part of my final code ;-)

          My final solution was O(RC) without any permutation checking.